From 3958bda489534564101c9614ce7a0eb2ae14dc67 Mon Sep 17 00:00:00 2001 From: synAdmin Date: Fri, 11 Sep 2026 10:01:26 -0500 Subject: [PATCH] fix(auth): offer Google on the sign-up tab, not only on Log In (#345) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The button was rendered inside the Log In tab's form only, so a visitor on Create Account saw no social option at all. Reported from a local run. The mistake came from following the passkey button too closely. A passkey belongs only on Log In, and correctly so: you cannot register an account with one, since registration requires an account to register it against. Google is the opposite case. Creating an account is precisely what a new customer reaches for it to do, so leaving it off the sign-up tab hid the feature from the people it helps most — and hid it on the tab the modal opens on by default. The label differs by tab and nothing else does. One endpoint serves both: it signs in a known identity, links a verified address, or creates an account, and the customer neither knows nor cares which will happen. So the wording matches what they came to that tab to do rather than what the server ends up doing. Both spellings are given in Google's identity guidelines alongside the mark. The two consent checkboxes above it are deliberately not carried across. Google takes the customer off this site entirely, and a tick that survived that round trip would be a consent recorded from a form nobody submitted. They are asked again, with the same wording and through the same endpoints, on the step they land on afterwards — which is what #342 built that step for. The end-to-end test asserts absence, like the one beside it, because local and QA have no credentials and absence is the behaviour that actually runs there. Verified: frontend tsc, lint and build clean. Co-Authored-By: Claude Opus 5 --- frontend/src/customer/AuthForm.tsx | 21 ++++++++++++++++++++ frontend/src/customer/GoogleSignInButton.tsx | 15 ++++++++++++-- frontend/tests/e2e/auth.spec.ts | 17 ++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/frontend/src/customer/AuthForm.tsx b/frontend/src/customer/AuthForm.tsx index b357f35..2f1b51f 100644 --- a/frontend/src/customer/AuthForm.tsx +++ b/frontend/src/customer/AuthForm.tsx @@ -233,6 +233,27 @@ export default function AuthForm({ mode, onModeChange, onForgotPassword, onSucce By creating an account you agree to our{' '} Privacy Policy. + + {/* On this tab too, and its absence here was a bug (#345). + A passkey belongs only on Log In, because you cannot + register an account with one — but creating an account is + exactly what a new customer reaches for Google to do, so + leaving it off the sign-up tab hid the feature from the + people it helps most. + + The two consent boxes above are not carried across. Google + takes the customer off this site entirely, and a tick that + survived that round trip would be a consent recorded from a + form nobody submitted. They are asked again, with the same + wording, on the step they land on (#342). */} + {googleEnabled && ( + <> + + or + + + + )} ) }, diff --git a/frontend/src/customer/GoogleSignInButton.tsx b/frontend/src/customer/GoogleSignInButton.tsx index 4ce5d4b..9cddcb9 100644 --- a/frontend/src/customer/GoogleSignInButton.tsx +++ b/frontend/src/customer/GoogleSignInButton.tsx @@ -37,6 +37,17 @@ function GoogleMark() { type Props = Readonly<{ /** Where to send the customer back to. Validated again on the server. */ returnTo: string; + /** + * Which tab this sits on, which changes only the wording. + * + * One endpoint serves both: it signs in a known identity, links a verified + * address, or creates an account. The customer does not know or care which + * of those will happen, so the label matches what they came to the tab to + * do rather than what the server ends up doing. + * + * Both spellings are in Google identity guidelines alongside the mark. + */ + intent?: 'sign-in' | 'sign-up'; }>; /** @@ -51,7 +62,7 @@ type Props = Readonly<{ * here. It has to be, since anyone can type the URL, and doing it in one place * beats doing it in two languages. See `google/returnTo.ts`. */ -export default function GoogleSignInButton({ returnTo }: Props) { +export default function GoogleSignInButton({ returnTo, intent = 'sign-in' }: Props) { return ( ); } diff --git a/frontend/tests/e2e/auth.spec.ts b/frontend/tests/e2e/auth.spec.ts index 2cd733d..7abb059 100755 --- a/frontend/tests/e2e/auth.spec.ts +++ b/frontend/tests/e2e/auth.spec.ts @@ -124,6 +124,23 @@ test.describe('Customer accounts', () => { // So the button being ABSENT is the behaviour under test here, and it is the // one that matters: a control that appears and then fails at Google is worse // than one that was never offered. + // The sign-up tab, which #345 left it off entirely. A passkey belongs only on + // Log In, because you cannot register an account with one — but creating an + // account is exactly what a new customer reaches for Google to do, so its + // absence there hid the feature from the people it helps most. + // + // Asserted as absent for the same reason as the login one: local and QA have + // no credentials, so absence is the behaviour that actually runs here. + test('offers no Google button on the sign-up tab either, when unconfigured', async ({ + authModal + }) => { + await authModal.gotoRegister(); + + await expect( + authModal.registerDialog.getByRole('button', { name: /with Google/i }) + ).toHaveCount(0); + }); + test('offers no Google button when the environment is not configured for it', async ({ authModal, accountModal,