diff --git a/frontend/locales/en.json b/frontend/locales/en.json
index 06e7627be..840980ab2 100644
--- a/frontend/locales/en.json
+++ b/frontend/locales/en.json
@@ -256,6 +256,8 @@
"password_confirm_label": "Confirm password",
"password_label": "Password",
"passwordless_notice": "This account doesn't need a password. We'll send a verification code to your email address instead.",
+ "pinned_email_error": "This invite's email address can't be used to create an account. Let whoever invited you know.",
+ "pinned_username_error": "The account this invite is for can't be created. Let whoever invited you know.",
"send_code": "Send code",
"terms_of_service": "I agree to the Terms and Conditions"
},
diff --git a/frontend/src/entrypoints/register.test.tsx b/frontend/src/entrypoints/register.test.tsx
index 768b04b40..ef65d669a 100644
--- a/frontend/src/entrypoints/register.test.tsx
+++ b/frontend/src/entrypoints/register.test.tsx
@@ -119,4 +119,64 @@ describe("register island", () => {
).toBeTruthy();
});
});
+
+ describe("with an invite pinning the username and email", () => {
+ const invite = {
+ valid: true,
+ username: "alice",
+ email: "alice@example.com",
+ passwordless: true,
+ };
+
+ it("explains an error on the username above the form", async () => {
+ await mountRegister({
+ invite,
+ form: {
+ errors: [],
+ fields: { username: { value: "", errors: [{ kind: "exists" }] } },
+ },
+ });
+
+ const alert = screen.getByRole("alert");
+ expect(alert).toHaveTextContent(
+ "The account this invite is for can't be created.",
+ );
+ expect(
+ alert.compareDocumentPosition(
+ screen.getByRole("button", { name: "Send code" }),
+ ) & Node.DOCUMENT_POSITION_FOLLOWING,
+ ).toBeTruthy();
+ });
+
+ it("explains an error on the email address above the form", async () => {
+ await mountRegister({
+ invite,
+ form: {
+ errors: [],
+ fields: {
+ email: {
+ value: "alice@example.com",
+ errors: [
+ {
+ kind: "policy",
+ code: "email-domain-banned",
+ message: "Email domain is banned",
+ },
+ ],
+ },
+ },
+ },
+ });
+
+ const alert = screen.getByRole("alert");
+ expect(alert).toHaveTextContent(
+ "This invite's email address can't be used to create an account.",
+ );
+ expect(
+ alert.compareDocumentPosition(
+ screen.getByRole("button", { name: "Send code" }),
+ ) & Node.DOCUMENT_POSITION_FOLLOWING,
+ ).toBeTruthy();
+ });
+ });
});
diff --git a/frontend/src/entrypoints/register.tsx b/frontend/src/entrypoints/register.tsx
index 18dab5845..08eca6087 100644
--- a/frontend/src/entrypoints/register.tsx
+++ b/frontend/src/entrypoints/register.tsx
@@ -381,6 +381,15 @@ const PasswordRegisterForm: React.FC<{ data: Data }> = ({ data }) => {