diff --git a/integration/presets/envs.ts b/integration/presets/envs.ts index 6d7f2f2b97..5d60c29d11 100644 --- a/integration/presets/envs.ts +++ b/integration/presets/envs.ts @@ -113,11 +113,14 @@ const withWaitlistdMode = withEmailCodes .setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('with-waitlist-mode').sk) .setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-waitlist-mode').pk); -const withCombinedFlow = withEmailCodes +const withSignInOrUpFlow = withEmailCodes .clone() - .setId('withCombinedFlow') - .setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('with-email-codes').sk) - .setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-email-codes').pk) + .setId('withSignInOrUpFlow') + .setEnvVariable('public', 'CLERK_SIGN_UP_URL', undefined); + +const withSignInOrUpEmailLinksFlow = withEmailLinks + .clone() + .setId('withSignInOrUpEmailLinksFlow') .setEnvVariable('public', 'CLERK_SIGN_UP_URL', undefined); export const envs = { @@ -136,5 +139,6 @@ export const envs = { withRestrictedMode, withLegalConsent, withWaitlistdMode, - withCombinedFlow, + withSignInOrUpFlow, + withSignInOrUpEmailLinksFlow, } as const; diff --git a/integration/presets/longRunningApps.ts b/integration/presets/longRunningApps.ts index cd1f27cc19..d5573f015e 100644 --- a/integration/presets/longRunningApps.ts +++ b/integration/presets/longRunningApps.ts @@ -31,7 +31,12 @@ export const createLongRunningApps = () => { }, { id: 'next.appRouter.withCustomRoles', config: next.appRouter, env: envs.withCustomRoles }, { id: 'next.appRouter.withReverification', config: next.appRouter, env: envs.withReverification }, - { id: 'next.appRouter.withCombinedFlow', config: next.appRouter, env: envs.withCombinedFlow }, + { id: 'next.appRouter.withSignInOrUpFlow', config: next.appRouter, env: envs.withSignInOrUpFlow }, + { + id: 'next.appRouter.withSignInOrUpEmailLinksFlow', + config: next.appRouter, + env: envs.withSignInOrUpEmailLinksFlow, + }, { id: 'quickstart.next.appRouter', config: next.appRouterQuickstart, env: envs.withEmailCodesQuickstart }, { id: 'elements.next.appRouter', config: elements.nextAppRouter, env: envs.withEmailCodes }, { id: 'astro.node.withCustomRoles', config: astro.node, env: envs.withCustomRoles }, diff --git a/integration/tests/combined-sign-in-flow.test.ts b/integration/tests/combined-sign-in-flow.test.ts deleted file mode 100644 index f0afacb4c4..0000000000 --- a/integration/tests/combined-sign-in-flow.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { expect, test } from '@playwright/test'; - -import { appConfigs } from '../presets'; -import { createTestUtils, type FakeUser, testAgainstRunningApps } from '../testUtils'; - -testAgainstRunningApps({ withEnv: [appConfigs.envs.withCombinedFlow] })('combined sign in flow @nextjs', ({ app }) => { - test.describe.configure({ mode: 'serial' }); - - let fakeUser: FakeUser; - - test.beforeAll(async () => { - const u = createTestUtils({ app }); - fakeUser = u.services.users.createFakeUser({ - withPhoneNumber: true, - withUsername: true, - }); - await u.services.users.createBapiUser(fakeUser); - }); - - test.afterAll(async () => { - await fakeUser.deleteIfExists(); - await app.teardown(); - }); - - test('flows are combined', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - - await expect(u.page.getByText(`Don’t have an account?`)).toBeHidden(); - }); - - test('sign in with email and password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - await u.po.signIn.setIdentifier(fakeUser.email); - await u.po.signIn.continue(); - await u.po.signIn.setPassword(fakeUser.password); - await u.po.signIn.continue(); - await u.po.expect.toBeSignedIn(); - }); - - test('sign in with email and instant password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.expect.toBeSignedIn(); - }); - - test('sign in with email code', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - await u.po.signIn.getIdentifierInput().fill(fakeUser.email); - await u.po.signIn.continue(); - await u.po.signIn.getUseAnotherMethodLink().click(); - await u.po.signIn.getAltMethodsEmailCodeButton().click(); - await u.po.signIn.enterTestOtpCode(); - await u.po.expect.toBeSignedIn(); - }); - - test('sign in with phone number and password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - await u.po.signIn.usePhoneNumberIdentifier().click(); - await u.po.signIn.getIdentifierInput().fill(fakeUser.phoneNumber); - await u.po.signIn.setPassword(fakeUser.password); - await u.po.signIn.continue(); - await u.po.expect.toBeSignedIn(); - }); - - test('sign in only with phone number', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - const fakeUserWithoutPassword = u.services.users.createFakeUser({ - fictionalEmail: true, - withPassword: false, - withPhoneNumber: true, - }); - await u.services.users.createBapiUser(fakeUserWithoutPassword); - await u.po.signIn.goTo(); - await u.po.signIn.usePhoneNumberIdentifier().click(); - await u.po.signIn.getIdentifierInput().fill(fakeUserWithoutPassword.phoneNumber); - await u.po.signIn.continue(); - await u.po.signIn.enterTestOtpCode(); - await u.po.expect.toBeSignedIn(); - - await fakeUserWithoutPassword.deleteIfExists(); - }); - - test('sign in with username and password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - await u.po.signIn.getIdentifierInput().fill(fakeUser.username); - await u.po.signIn.setPassword(fakeUser.password); - await u.po.signIn.continue(); - await u.po.expect.toBeSignedIn(); - }); - - test('can reset password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - const fakeUserWithPasword = u.services.users.createFakeUser({ - fictionalEmail: true, - withPassword: true, - }); - await u.services.users.createBapiUser(fakeUserWithPasword); - - await u.po.signIn.goTo(); - await u.po.signIn.getIdentifierInput().fill(fakeUserWithPasword.email); - await u.po.signIn.continue(); - await u.po.signIn.getForgotPassword().click(); - await u.po.signIn.getResetPassword().click(); - await u.po.signIn.enterTestOtpCode(); - await u.po.signIn.setPassword(`${fakeUserWithPasword.password}_reset`); - await u.po.signIn.setPasswordConfirmation(`${fakeUserWithPasword.password}_reset`); - await u.po.signIn.getResetPassword().click(); - await u.po.expect.toBeSignedIn(); - - await fakeUserWithPasword.deleteIfExists(); - }); - - test('cannot sign in with wrong password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - - await u.po.signIn.goTo(); - await u.po.signIn.getIdentifierInput().fill(fakeUser.email); - await u.po.signIn.continue(); - await u.po.signIn.setPassword('wrong-password'); - await u.po.signIn.continue(); - await expect(u.page.getByText(/password you entered is incorrect/i)).toBeVisible(); - - await u.po.expect.toBeSignedOut(); - }); - - test('cannot sign in with wrong password but can sign in with email', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - - await u.po.signIn.goTo(); - await u.po.signIn.getIdentifierInput().fill(fakeUser.email); - await u.po.signIn.continue(); - await u.po.signIn.setPassword('wrong-password'); - await u.po.signIn.continue(); - - await expect(u.page.getByText(/password you entered is incorrect/i)).toBeVisible(); - - await u.po.signIn.getUseAnotherMethodLink().click(); - await u.po.signIn.getAltMethodsEmailCodeButton().click(); - await u.po.signIn.enterTestOtpCode(); - - await u.po.expect.toBeSignedIn(); - }); - - test('access protected page @express', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - await u.po.signIn.goTo(); - await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.expect.toBeSignedIn(); - - expect(await u.page.locator("data-test-id='protected-api-response'").count()).toEqual(0); - await u.page.goToRelative('/protected'); - await u.page.isVisible("data-test-id='protected-api-response'"); - }); -}); diff --git a/integration/tests/combined-sign-up-flow.test.ts b/integration/tests/combined-sign-up-flow.test.ts deleted file mode 100644 index 93818d0b95..0000000000 --- a/integration/tests/combined-sign-up-flow.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { expect, test } from '@playwright/test'; - -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; - -testAgainstRunningApps({ withEnv: [appConfigs.envs.withCombinedFlow] })('combined sign up flow @nextjs', ({ app }) => { - test.describe.configure({ mode: 'serial' }); - - test.afterAll(async () => { - await app.teardown(); - }); - - test('sign up with email and password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - const fakeUser = u.services.users.createFakeUser({ - fictionalEmail: true, - withPassword: true, - }); - - // Go to sign in page - await u.po.signIn.goTo(); - - // Fill in sign in form - await u.po.signIn.setIdentifier(fakeUser.email); - await u.po.signIn.continue(); - await u.page.waitForAppUrl('/sign-in/create'); - - const prefilledEmail = await u.po.signUp.getEmailAddressInput().inputValue(); - expect(prefilledEmail).toBe(fakeUser.email); - - await u.po.signUp.setPassword(fakeUser.password); - await u.po.signUp.continue(); - - // Verify email - await u.po.signUp.enterTestOtpCode(); - - // Check if user is signed in - await u.po.expect.toBeSignedIn(); - - await fakeUser.deleteIfExists(); - }); - - test('sign up with username, email, and password', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - const fakeUser = u.services.users.createFakeUser({ - fictionalEmail: true, - withPassword: true, - withUsername: true, - }); - - await u.po.signIn.goTo(); - await u.po.signIn.setIdentifier(fakeUser.username); - await u.po.signIn.continue(); - await u.page.waitForAppUrl('/sign-in/create'); - - const prefilledUsername = await u.po.signUp.getUsernameInput().inputValue(); - expect(prefilledUsername).toBe(fakeUser.username); - - await u.po.signUp.setEmailAddress(fakeUser.email); - await u.po.signUp.setPassword(fakeUser.password); - await u.po.signUp.continue(); - - await u.po.signUp.enterTestOtpCode(); - - await u.po.expect.toBeSignedIn(); - - await fakeUser.deleteIfExists(); - }); - - test('sign up, sign out and sign in again', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - const fakeUser = u.services.users.createFakeUser({ - fictionalEmail: true, - withPassword: true, - withUsername: true, - }); - - // Go to sign in page - await u.po.signIn.goTo(); - - // Fill in sign in form - await u.po.signIn.setIdentifier(fakeUser.email); - await u.po.signIn.continue(); - await u.page.waitForAppUrl('/sign-in/create'); - - const prefilledEmail = await u.po.signUp.getEmailAddressInput().inputValue(); - expect(prefilledEmail).toBe(fakeUser.email); - - await u.po.signUp.setPassword(fakeUser.password); - await u.po.signUp.continue(); - - // Verify email - await u.po.signUp.enterTestOtpCode(); - - // Check if user is signed in - await u.po.expect.toBeSignedIn(); - - // Toggle user button - await u.po.userButton.toggleTrigger(); - await u.po.userButton.waitForPopover(); - - // Click sign out - await u.po.userButton.triggerSignOut(); - - // Check if user is signed out - await u.po.expect.toBeSignedOut(); - - // Go to sign in page - await u.po.signIn.goTo(); - - // Fill in sign in form - await u.po.signIn.signInWithEmailAndInstantPassword({ - email: fakeUser.email, - password: fakeUser.password, - }); - - // Check if user is signed in - await u.po.expect.toBeSignedIn(); - - await fakeUser.deleteIfExists(); - }); -}); diff --git a/integration/tests/sign-in-flow.test.ts b/integration/tests/sign-in-flow.test.ts index 29243df5c4..1a6a833cd8 100644 --- a/integration/tests/sign-in-flow.test.ts +++ b/integration/tests/sign-in-flow.test.ts @@ -141,7 +141,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign in f await u.po.expect.toBeSignedIn(); }); - test('access protected page @express', async ({ page, context }) => { + test('access protected page', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); diff --git a/integration/tests/sign-in-or-up-email-links-flow.test.ts b/integration/tests/sign-in-or-up-email-links-flow.test.ts new file mode 100644 index 0000000000..a49a867e1f --- /dev/null +++ b/integration/tests/sign-in-or-up-email-links-flow.test.ts @@ -0,0 +1,69 @@ +import { expect, test } from '@playwright/test'; + +import { appConfigs } from '../presets'; +import type { FakeUser } from '../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../testUtils'; + +testAgainstRunningApps({ withEnv: [appConfigs.envs.withSignInOrUpEmailLinksFlow] })( + 'sign-in-or-up email links flow @nextjs', + ({ app }) => { + test.describe.configure({ mode: 'serial' }); + + let fakeUser: FakeUser; + + test.beforeAll(() => { + const u = createTestUtils({ app }); + fakeUser = u.services.users.createFakeUser({ + fictionalEmail: false, + withPassword: true, + }); + }); + + test.afterAll(async () => { + await app.teardown(); + }); + + test('sign up with email link', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.setIdentifier(fakeUser.email); + await u.po.signIn.continue(); + await u.page.waitForAppUrl('/sign-in/create'); + + const prefilledEmail = await u.po.signUp.getEmailAddressInput().inputValue(); + expect(prefilledEmail).toBe(fakeUser.email); + + await u.po.signUp.setPassword(fakeUser.password); + await u.po.signUp.continue(); + + await u.po.signUp.waitForEmailVerificationScreen(); + await u.tabs.runInNewTab(async u => { + const verificationLink = await u.services.email.getVerificationLinkForEmailAddress(fakeUser.email); + await u.page.goto(verificationLink); + await u.po.expect.toBeSignedIn(); + await u.page.close(); + }); + await u.po.expect.toBeSignedIn(); + }); + + test('sign in with email link', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.setIdentifier(fakeUser.email); + await u.po.signIn.continue(); + await u.page.waitForAppUrl('/sign-in/factor-one'); + // Defaults to password, so we need to switch to email link + await u.page.getByRole('link', { name: /Use another method/i }).click(); + await u.page.getByRole('button', { name: /Email link to/i }).click(); + await page.getByRole('heading', { name: /Check your email/i }).waitFor(); + await u.tabs.runInNewTab(async u => { + const verificationLink = await u.services.email.getVerificationLinkForEmailAddress(fakeUser.email); + await u.page.goto(verificationLink); + await u.po.expect.toBeSignedIn(); + await u.page.close(); + }); + await u.po.expect.toBeSignedIn(); + await fakeUser.deleteIfExists(); + }); + }, +); diff --git a/integration/tests/sign-in-or-up-flow.test.ts b/integration/tests/sign-in-or-up-flow.test.ts new file mode 100644 index 0000000000..2fdcbb5572 --- /dev/null +++ b/integration/tests/sign-in-or-up-flow.test.ts @@ -0,0 +1,286 @@ +import { expect, test } from '@playwright/test'; + +import { appConfigs } from '../presets'; +import { createTestUtils, type FakeUser, testAgainstRunningApps } from '../testUtils'; + +testAgainstRunningApps({ withEnv: [appConfigs.envs.withSignInOrUpFlow] })('sign-in-or-up flow @nextjs', ({ app }) => { + test.describe.configure({ mode: 'serial' }); + + test.afterAll(async () => { + await app.teardown(); + }); + + test.describe('sign-in', () => { + let fakeUser: FakeUser; + + test.beforeAll(async () => { + const u = createTestUtils({ app }); + fakeUser = u.services.users.createFakeUser({ + withPhoneNumber: true, + withUsername: true, + }); + await u.services.users.createBapiUser(fakeUser); + }); + + test.afterAll(async () => { + await fakeUser.deleteIfExists(); + }); + + test('flows are combined', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + + await expect(u.page.getByText(`Don’t have an account?`)).toBeHidden(); + }); + + test('sign in with email and password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.setIdentifier(fakeUser.email); + await u.po.signIn.continue(); + await u.po.signIn.setPassword(fakeUser.password); + await u.po.signIn.continue(); + await u.po.expect.toBeSignedIn(); + }); + + test('sign in with email and instant password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); + await u.po.expect.toBeSignedIn(); + }); + + test('sign in with email code', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.getIdentifierInput().fill(fakeUser.email); + await u.po.signIn.continue(); + await u.po.signIn.getUseAnotherMethodLink().click(); + await u.po.signIn.getAltMethodsEmailCodeButton().click(); + await u.po.signIn.enterTestOtpCode(); + await u.po.expect.toBeSignedIn(); + }); + + test('sign in with phone number and password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.usePhoneNumberIdentifier().click(); + await u.po.signIn.getIdentifierInput().fill(fakeUser.phoneNumber); + await u.po.signIn.setPassword(fakeUser.password); + await u.po.signIn.continue(); + await u.po.expect.toBeSignedIn(); + }); + + test('sign in only with phone number', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + const fakeUserWithoutPassword = u.services.users.createFakeUser({ + fictionalEmail: true, + withPassword: false, + withPhoneNumber: true, + }); + await u.services.users.createBapiUser(fakeUserWithoutPassword); + await u.po.signIn.goTo(); + await u.po.signIn.usePhoneNumberIdentifier().click(); + await u.po.signIn.getIdentifierInput().fill(fakeUserWithoutPassword.phoneNumber); + await u.po.signIn.continue(); + await u.po.signIn.enterTestOtpCode(); + await u.po.expect.toBeSignedIn(); + + await fakeUserWithoutPassword.deleteIfExists(); + }); + + test('sign in with username and password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.getIdentifierInput().fill(fakeUser.username); + await u.po.signIn.setPassword(fakeUser.password); + await u.po.signIn.continue(); + await u.po.expect.toBeSignedIn(); + }); + + test('can reset password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + const fakeUserWithPasword = u.services.users.createFakeUser({ + fictionalEmail: true, + withPassword: true, + }); + await u.services.users.createBapiUser(fakeUserWithPasword); + + await u.po.signIn.goTo(); + await u.po.signIn.getIdentifierInput().fill(fakeUserWithPasword.email); + await u.po.signIn.continue(); + await u.po.signIn.getForgotPassword().click(); + await u.po.signIn.getResetPassword().click(); + await u.po.signIn.enterTestOtpCode(); + await u.po.signIn.setPassword(`${fakeUserWithPasword.password}_reset`); + await u.po.signIn.setPasswordConfirmation(`${fakeUserWithPasword.password}_reset`); + await u.po.signIn.getResetPassword().click(); + await u.po.expect.toBeSignedIn(); + + await fakeUserWithPasword.deleteIfExists(); + }); + + test('cannot sign in with wrong password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + + await u.po.signIn.goTo(); + await u.po.signIn.getIdentifierInput().fill(fakeUser.email); + await u.po.signIn.continue(); + await u.po.signIn.setPassword('wrong-password'); + await u.po.signIn.continue(); + await expect(u.page.getByText(/password you entered is incorrect/i)).toBeVisible(); + + await u.po.expect.toBeSignedOut(); + }); + + test('cannot sign in with wrong password but can sign in with email', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + + await u.po.signIn.goTo(); + await u.po.signIn.getIdentifierInput().fill(fakeUser.email); + await u.po.signIn.continue(); + await u.po.signIn.setPassword('wrong-password'); + await u.po.signIn.continue(); + + await expect(u.page.getByText(/password you entered is incorrect/i)).toBeVisible(); + + await u.po.signIn.getUseAnotherMethodLink().click(); + await u.po.signIn.getAltMethodsEmailCodeButton().click(); + await u.po.signIn.enterTestOtpCode(); + + await u.po.expect.toBeSignedIn(); + }); + + test('access protected page', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo(); + await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); + await u.po.expect.toBeSignedIn(); + + expect(await u.page.locator("data-test-id='protected-api-response'").count()).toEqual(0); + await u.page.goToRelative('/protected'); + await u.page.isVisible("data-test-id='protected-api-response'"); + }); + + test('sign up with email and password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + const fakeUser = u.services.users.createFakeUser({ + fictionalEmail: true, + withPassword: true, + }); + + // Go to sign in page + await u.po.signIn.goTo(); + + // Fill in sign in form + await u.po.signIn.setIdentifier(fakeUser.email); + await u.po.signIn.continue(); + await u.page.waitForAppUrl('/sign-in/create'); + + const prefilledEmail = await u.po.signUp.getEmailAddressInput().inputValue(); + expect(prefilledEmail).toBe(fakeUser.email); + + await u.po.signUp.setPassword(fakeUser.password); + await u.po.signUp.continue(); + + // Verify email + await u.po.signUp.enterTestOtpCode(); + + // Check if user is signed in + await u.po.expect.toBeSignedIn(); + + await fakeUser.deleteIfExists(); + }); + }); + + test.describe('sign-up', () => { + test('sign up with username, email, and password', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + const fakeUser = u.services.users.createFakeUser({ + fictionalEmail: true, + withPassword: true, + withUsername: true, + }); + + await u.po.signIn.goTo(); + await u.po.signIn.setIdentifier(fakeUser.username); + await u.po.signIn.continue(); + await u.page.waitForAppUrl('/sign-in/create'); + + const prefilledUsername = await u.po.signUp.getUsernameInput().inputValue(); + expect(prefilledUsername).toBe(fakeUser.username); + + await u.po.signUp.setEmailAddress(fakeUser.email); + await u.po.signUp.setPassword(fakeUser.password); + await u.po.signUp.continue(); + + await u.po.signUp.enterTestOtpCode(); + + await u.po.expect.toBeSignedIn(); + + await fakeUser.deleteIfExists(); + }); + + test('sign up, sign out and sign in again', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + const fakeUser = u.services.users.createFakeUser({ + fictionalEmail: true, + withPassword: true, + withUsername: true, + }); + + // Go to sign in page + await u.po.signIn.goTo(); + + // Fill in sign in form + await u.po.signIn.setIdentifier(fakeUser.email); + await u.po.signIn.continue(); + await u.page.waitForAppUrl('/sign-in/create'); + + const prefilledEmail = await u.po.signUp.getEmailAddressInput().inputValue(); + expect(prefilledEmail).toBe(fakeUser.email); + + await u.po.signUp.setPassword(fakeUser.password); + await u.po.signUp.continue(); + + // Verify email + await u.po.signUp.enterTestOtpCode(); + + // Check if user is signed in + await u.po.expect.toBeSignedIn(); + + // Toggle user button + await u.po.userButton.toggleTrigger(); + await u.po.userButton.waitForPopover(); + + // Click sign out + await u.po.userButton.triggerSignOut(); + + // Check if user is signed out + await u.po.expect.toBeSignedOut(); + + // Go to sign in page + await u.po.signIn.goTo(); + + // Fill in sign in form + await u.po.signIn.signInWithEmailAndInstantPassword({ + email: fakeUser.email, + password: fakeUser.password, + }); + + // Check if user is signed in + await u.po.expect.toBeSignedIn(); + + await fakeUser.deleteIfExists(); + }); + + test('sign in with ticket renders sign up', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.po.signIn.goTo({ + searchParams: new URLSearchParams({ __clerk_ticket: '123', __clerk_status: 'sign_up' }), + }); + await u.page.waitForAppUrl('/sign-in/create'); + await expect(u.page.getByText(`Create your account`)).toBeVisible(); + }); + }); +});