Skip to content

Commit 5475d2a

Browse files
authored
feat(e2e): Add OAuth provider flow e2e tests (#4984)
1 parent 11c6458 commit 5475d2a

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

integration/templates/next-app-router/src/app/layout.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ export const metadata = {
1212
export default function RootLayout({ children }: { children: React.ReactNode }) {
1313
return (
1414
<ClerkProvider
15+
appearance={{
16+
layout: {
17+
// Icon buttons only contain accessible labels when they use an icon; our generated letter icon does not have
18+
// an accessible label. Using the "blockButton" variant ensures that the button contains a visible label that
19+
// can be selected by a Playwright selector.
20+
socialButtonsVariant: 'blockButton',
21+
},
22+
}}
1523
experimental={{
1624
persistClient: process.env.NEXT_PUBLIC_EXPERIMENTAL_PERSIST_CLIENT
1725
? process.env.NEXT_PUBLIC_EXPERIMENTAL_PERSIST_CLIENT === 'true'
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { test } from '@playwright/test';
2+
import { createClerkClient } from '@clerk/backend';
3+
4+
import { appConfigs } from '../presets';
5+
import type { FakeUser } from '../testUtils';
6+
import { createTestUtils, testAgainstRunningApps } from '../testUtils';
7+
import { instanceKeys } from '../presets/envs';
8+
import { createUserService } from '../testUtils/usersService';
9+
10+
testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('oauth flows @nextjs', ({ app }) => {
11+
test.describe.configure({ mode: 'serial' });
12+
13+
let fakeUser: FakeUser;
14+
15+
test.beforeAll(async () => {
16+
// Create a clerkClient for the OAuth provider instance.
17+
const client = createClerkClient({
18+
secretKey: instanceKeys.get('oauth-provider').sk,
19+
publishableKey: instanceKeys.get('oauth-provider').pk,
20+
});
21+
const users = createUserService(client);
22+
fakeUser = users.createFakeUser({
23+
withUsername: true,
24+
});
25+
// Create the user on the OAuth provider instance so we do not need to sign up twice.
26+
await users.createBapiUser(fakeUser);
27+
});
28+
29+
test.afterAll(async () => {
30+
const u = createTestUtils({ app });
31+
// Delete the user on the OAuth provider instance.
32+
await fakeUser.deleteIfExists();
33+
// Delete the user on the app instance.
34+
await u.services.users.deleteIfExists({ email: fakeUser.email });
35+
await app.teardown();
36+
});
37+
38+
test('sign up with custom oauth provider', async ({ page, context }) => {
39+
const u = createTestUtils({ app, page, context });
40+
await u.po.signUp.goTo();
41+
42+
await u.page.getByRole('button', { name: 'E2E OAuth Provider' }).click();
43+
await u.page.getByText('Sign in to oauth-provider').waitFor();
44+
45+
await u.po.signIn.setIdentifier(fakeUser.email);
46+
await u.po.signIn.continue();
47+
await u.po.signIn.enterTestOtpCode();
48+
49+
// We can't use our `expect.toBeSignedIn` first because that would result in `true` on the OAuth provider instance.
50+
// We want to assert that we're signed in on our app instance, which will render the text 'SignedIn'.
51+
await u.page.getByText('SignedIn').waitFor();
52+
await u.po.expect.toBeSignedIn();
53+
});
54+
55+
test('sign in with custom oauth provider', async ({ page, context }) => {
56+
const u = createTestUtils({ app, page, context });
57+
await u.po.signIn.goTo();
58+
59+
await u.page.getByRole('button', { name: 'E2E OAuth Provider' }).click();
60+
await u.page.getByText('Sign in to oauth-provider').waitFor();
61+
62+
await u.po.signIn.setIdentifier(fakeUser.email);
63+
await u.po.signIn.continue();
64+
await u.po.signIn.enterTestOtpCode();
65+
66+
// We can't use our `expect.toBeSignedIn` first because that would result in `true` on the OAuth provider instance.
67+
// We want to assert that we're signed in on our app instance, which will render the text 'SignedIn'.
68+
await u.page.getByText('SignedIn').waitFor();
69+
await u.po.expect.toBeSignedIn();
70+
});
71+
72+
test('sign in modal', async ({ page, context }) => {
73+
const u = createTestUtils({ app, page, context });
74+
75+
await u.page.goToRelative('/buttons');
76+
await u.page.waitForClerkJsLoaded();
77+
await u.po.expect.toBeSignedOut();
78+
79+
await u.page.getByText('Sign in button (force)').click();
80+
81+
await u.po.signIn.waitForMounted();
82+
await u.page.getByRole('button', { name: 'E2E OAuth Provider' }).click();
83+
await u.page.getByText('Sign in to oauth-provider').waitFor();
84+
85+
await u.po.signIn.setIdentifier(fakeUser.email);
86+
await u.po.signIn.continue();
87+
await u.po.signIn.enterTestOtpCode();
88+
89+
await u.page.waitForAppUrl('/protected');
90+
91+
await u.po.expect.toBeSignedIn();
92+
});
93+
94+
test('sign up modal', async ({ page, context }) => {
95+
const u = createTestUtils({ app, page, context });
96+
// The SignUpModal will only redirect to its provided forceRedirectUrl if the user is signing up; it will not
97+
// redirect if the sign up is transfered to a sign in.
98+
await u.services.users.deleteIfExists({ email: fakeUser.email });
99+
100+
await u.page.goToRelative('/buttons');
101+
await u.page.waitForClerkJsLoaded();
102+
await u.po.expect.toBeSignedOut();
103+
104+
await u.page.getByText('Sign up button (force)').click();
105+
106+
await u.po.signUp.waitForMounted();
107+
await u.page.getByRole('button', { name: 'E2E OAuth Provider' }).click();
108+
await u.page.getByText('Sign in to oauth-provider').waitFor();
109+
110+
await u.po.signIn.setIdentifier(fakeUser.email);
111+
await u.po.signIn.continue();
112+
await u.po.signIn.enterTestOtpCode();
113+
114+
await u.page.waitForAppUrl('/protected');
115+
});
116+
});

0 commit comments

Comments
 (0)