fix(ui): accept guest email addresses in member forms (#45688)

Co-authored-by: moyai-devin-berriai[bot] <336287033+moyai-devin-berriai[bot]@users.noreply.github.com>
This commit is contained in:
moyai-devin-berriai[bot] 2026-10-09 17:17:37 -07:00 • committed by GitHub
parent 141dba2372
commit 627356d3a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 8 deletions

View file

@ -227,15 +227,40 @@ describe("EditMembership submit payload", () => {
expect(submitted().role).toBe("admin");
});
it("blocks submission when the email is not an address", async () => {
renderEdit(orgMemberConfig, { user_id: "u1", user_email: "a@b.com", role: "user" });
it.each(["john_example.com#EXT#@tenant.onmicrosoft.com", "john#tag@example.com"])(
"saves budget and limit edits for %s",
async (user_email) => {
renderEdit(teamMemberConfig, { ...cappedMember, user_email });
fireEvent.change(screen.getByLabelText("Email"), { target: { value: "not-an-email" } });
save();
fireEvent.change(screen.getByLabelText("Team Member Budget (USD)"), { target: { value: "25" } });
fireEvent.change(screen.getByLabelText("Team Member TPM Limit"), { target: { value: "100" } });
fireEvent.change(screen.getByLabelText("Team Member RPM Limit"), { target: { value: "10" } });
save();
expect(await screen.findByText("Please enter a valid email!")).toBeInTheDocument();
expect(onSubmit).not.toHaveBeenCalled();
});
await waitFor(() => expect(onSubmit).toHaveBeenCalledOnce());
const expectedChanges = {
user_id: "u1",
user_email,
max_budget_in_team: "25",
tpm_limit: "100",
rpm_limit: "10",
};
expect(submitted()).toEqual(expect.objectContaining(expectedChanges));
},
);
it.each(["not-an-email", "john@@example.com", "john tag@example.com", "john@example#com"])(
"blocks submission for an invalid address: %s",
async (user_email) => {
renderEdit(orgMemberConfig, { user_id: "u1", user_email: "a@b.com", role: "user" });
fireEvent.change(screen.getByLabelText("Email"), { target: { value: user_email } });
save();
expect(await screen.findByText("Please enter a valid email!")).toBeInTheDocument();
expect(onSubmit).not.toHaveBeenCalled();
},
);
it("blocks submission when no role is selected", async () => {
renderEdit(orgMemberConfig, { user_id: "u1", user_email: "a@b.com", role: "" });

View file

@ -48,7 +48,8 @@ interface MemberModalProps<T extends BaseMember> {
const ROLE_REQUIRED_MESSAGE = "Please select a role!";
const isEmailish = (value: string): boolean => value === "" || z.email().safeParse(value).success;
const isEmailish = (value: string): boolean =>
value === "" || z.email({ pattern: z.regexes.html5Email }).safeParse(value).success;
const memberFieldSchema = z.union([z.string(), z.number(), z.null(), z.array(z.string())]).optional();