Skip to content

Commit 698d5d7

Browse files
authored
feat(repo,testing): Apply testing tokens to E2E tests (#5561)
1 parent 3a2b439 commit 698d5d7

21 files changed

+152
-55
lines changed

.changeset/cute-berries-design.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/testing': patch
3+
---
4+
5+
6+
Update `setupClerk` to handle the explict setting of secret keys via `setupClerk({ secretKey: 'sk_test_***' })`

.changeset/rich-breads-play.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/testing': patch
3+
---
4+
5+
Update `setupClerk` to enable skipping of the automatic loading of dot env files via `setupClerk({ dotenv: false })`

integration/models/longRunningApplication.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { parsePublishableKey } from '@clerk/shared/keys';
2+
import { clerkSetup } from '@clerk/testing/playwright';
3+
14
import { awaitableTreekill, fs } from '../scripts';
25
import type { Application } from './application';
36
import type { ApplicationConfig } from './applicationConfig';
@@ -56,6 +59,25 @@ export const longRunningApplication = (params: LongRunningApplicationParams) =>
5659
// will be called by global.setup.ts and by the test runner
5760
// the first time this is called, the app starts and the state is persisted in the state file
5861
init: async () => {
62+
try {
63+
const publishableKey = params.env.publicVariables.get('CLERK_PUBLISHABLE_KEY');
64+
const secretKey = params.env.privateVariables.get('CLERK_SECRET_KEY');
65+
const { instanceType, frontendApi: frontendApiUrl } = parsePublishableKey(publishableKey);
66+
67+
if (instanceType !== 'development') {
68+
console.log('Clerk: skipping setup of testing tokens for non-development instance');
69+
} else {
70+
await clerkSetup({
71+
publishableKey,
72+
frontendApiUrl,
73+
secretKey,
74+
dotenv: false,
75+
});
76+
}
77+
} catch (error) {
78+
console.error('Error setting up testing tokens:', error);
79+
throw error;
80+
}
5981
try {
6082
app = await config.commit();
6183
} catch (error) {

integration/testUtils/appPageObject.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
1+
import { setupClerkTestingToken } from '@clerk/testing/playwright';
12
import type { Page } from '@playwright/test';
23

34
import type { Application } from '../models/application';
45

5-
export const createAppPageObject = (testArgs: { page: Page }, app: Application) => {
6-
const { page } = testArgs;
6+
export const createAppPageObject = (testArgs: { page: Page; useTestingToken?: boolean }, app: Application) => {
7+
const { page, useTestingToken = true } = testArgs;
78
const appPage = Object.create(page) as Page;
89
const helpers = {
910
goToAppHome: async () => {
1011
try {
12+
if (useTestingToken) {
13+
await setupClerkTestingToken({ page });
14+
}
15+
1116
await page.goto(app.serverUrl);
1217
} catch {
1318
// do not fail the test if interstitial is returned (401)
1419
}
1520
},
16-
goToRelative: (path: string, opts: { waitUntil?: any; searchParams?: URLSearchParams; timeout?: number } = {}) => {
21+
goToRelative: async (
22+
path: string,
23+
opts: { waitUntil?: any; searchParams?: URLSearchParams; timeout?: number } = {},
24+
) => {
1725
let url: URL;
1826

1927
try {
@@ -35,6 +43,11 @@ export const createAppPageObject = (testArgs: { page: Page }, app: Application)
3543
if (opts.searchParams) {
3644
url.search = opts.searchParams.toString();
3745
}
46+
47+
if (useTestingToken) {
48+
await setupClerkTestingToken({ page });
49+
}
50+
3851
return page.goto(url.toString(), { timeout: opts.timeout ?? 20000, waitUntil: opts.waitUntil });
3952
},
4053
waitForClerkJsLoaded: async () => {

integration/testUtils/index.ts

+28-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createClerkClient as backendCreateClerkClient } from '@clerk/backend';
2+
import { setupClerkTestingToken } from '@clerk/testing/playwright';
23
import type { Browser, BrowserContext, Page, Response } from '@playwright/test';
34
import { expect } from '@playwright/test';
45

@@ -75,55 +76,65 @@ const createClerkUtils = ({ page }: TestArgs) => {
7576
};
7677
};
7778

79+
const createTestingTokenUtils = ({ page }: TestArgs) => {
80+
return {
81+
setup: async () => setupClerkTestingToken({ page }),
82+
};
83+
};
84+
7885
export type CreateAppPageObjectArgs = { page: Page; context: BrowserContext; browser: Browser };
7986

8087
export const createTestUtils = <
81-
Params extends { app: Application } & Partial<CreateAppPageObjectArgs>,
88+
Params extends { app: Application; useTestingToken?: boolean } & Partial<CreateAppPageObjectArgs>,
8289
Services = typeof services,
8390
PO = typeof pageObjects,
8491
BH = typeof browserHelpers,
85-
FullReturn = { services: Services; po: PO; tabs: BH; page: EnchancedPage; nexJsVersion: string },
92+
FullReturn = { services: Services; po: PO; tabs: BH; page: EnchancedPage; nextJsVersion: string },
8693
OnlyAppReturn = { services: Services },
8794
>(
8895
params: Params,
8996
): Params extends Partial<CreateAppPageObjectArgs> ? FullReturn : OnlyAppReturn => {
90-
const { app, context, browser } = params || {};
97+
const { app, context, browser, useTestingToken = true } = params || {};
9198

9299
const clerkClient = createClerkClient(app);
93100
const services = {
101+
clerk: clerkClient,
94102
email: createEmailService(),
95103
users: createUserService(clerkClient),
96104
invitations: createInvitationService(clerkClient),
97105
organizations: createOrganizationsService(clerkClient),
98-
clerk: clerkClient,
99106
};
100107

101108
if (!params.page) {
102109
return { services } as any;
103110
}
104111

105-
const page = createAppPageObject({ page: params.page }, app);
112+
const page = createAppPageObject({ page: params.page, useTestingToken }, app);
106113
const testArgs = { page, context, browser };
107114

108115
const pageObjects = {
116+
clerk: createClerkUtils(testArgs),
117+
expect: createExpectPageObject(testArgs),
109118
keylessPopover: createKeylessPopoverPageObject(testArgs),
110-
signUp: createSignUpComponentPageObject(testArgs),
111-
signIn: createSignInComponentPageObject(testArgs),
112-
userProfile: createUserProfileComponentPageObject(testArgs),
113119
organizationSwitcher: createOrganizationSwitcherComponentPageObject(testArgs),
120+
sessionTask: createSessionTaskComponentPageObject(testArgs),
121+
signIn: createSignInComponentPageObject(testArgs),
122+
signUp: createSignUpComponentPageObject(testArgs),
123+
testingToken: createTestingTokenUtils(testArgs),
114124
userButton: createUserButtonPageObject(testArgs),
125+
userProfile: createUserProfileComponentPageObject(testArgs),
115126
userVerification: createUserVerificationComponentPageObject(testArgs),
116127
waitlist: createWaitlistComponentPageObject(testArgs),
117-
sessionTask: createSessionTaskComponentPageObject(testArgs),
118-
expect: createExpectPageObject(testArgs),
119-
clerk: createClerkUtils(testArgs),
120128
};
121129

122130
const browserHelpers = {
123131
runInNewTab: async (
124132
cb: (u: { services: Services; po: PO; page: EnchancedPage }, context: BrowserContext) => Promise<unknown>,
125133
) => {
126-
const u = createTestUtils({ app, page: createAppPageObject({ page: await context.newPage() }, app) });
134+
const u = createTestUtils({
135+
app,
136+
page: createAppPageObject({ page: await context.newPage(), useTestingToken }, app),
137+
});
127138
await cb(u as any, context);
128139
return u;
129140
},
@@ -134,7 +145,10 @@ export const createTestUtils = <
134145
throw new Error('Browser is not defined. Did you forget to pass it to createPageObjects?');
135146
}
136147
const context = await browser.newContext();
137-
const u = createTestUtils({ app, page: createAppPageObject({ page: await context.newPage() }, app) });
148+
const u = createTestUtils({
149+
app,
150+
page: createAppPageObject({ page: await context.newPage(), useTestingToken }, app),
151+
});
138152
await cb(u as any, context);
139153
return u;
140154
},
@@ -146,7 +160,7 @@ export const createTestUtils = <
146160
po: pageObjects,
147161
tabs: browserHelpers,
148162
// eslint-disable-next-line turbo/no-undeclared-env-vars
149-
nexJsVersion: process.env.E2E_NEXTJS_VERSION,
163+
nextJsVersion: process.env.E2E_NEXTJS_VERSION,
150164
} as any;
151165
};
152166

integration/tests/email-link.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ const performSignUpVerificationLinkSameDevice = async (
8787
await u.po.signUp.waitForEmailVerificationScreen();
8888
await u.tabs.runInNewTab(async u => {
8989
const verificationLink = await u.services.email.getVerificationLinkForEmailAddress(fakeUser.email);
90+
91+
await u.po.testingToken.setup();
9092
await u.page.goto(verificationLink);
9193
await u.po.expect.toBeSignedIn();
9294
await u.page.close();
@@ -109,6 +111,8 @@ const performSignUpVerificationLinkDifferentDevice = async (
109111
await u.po.signUp.waitForEmailVerificationScreen();
110112
await u.tabs.runInNewBrowser(async u => {
111113
const verificationLink = await u.services.email.getVerificationLinkForEmailAddress(fakeUser.email);
114+
115+
await u.po.testingToken.setup();
112116
await u.page.goto(verificationLink);
113117
await u.po.expect.toBeSignedOut();
114118
await u.page.pause();

integration/tests/localhost/localhost-different-port-different-instance.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ test.describe('multiple apps running on localhost using different Clerk instance
4141
test('sessions are independent between the different apps', async ({ context }) => {
4242
const pages = await Promise.all([context.newPage(), context.newPage()]);
4343
const u = [
44-
createTestUtils({ app: apps[0].app, page: pages[0], context }),
45-
createTestUtils({ app: apps[1].app, page: pages[1], context }),
44+
createTestUtils({ app: apps[0].app, page: pages[0], context, useTestingToken: false }),
45+
createTestUtils({ app: apps[1].app, page: pages[1], context, useTestingToken: false }),
4646
];
4747

4848
await u[0].po.signIn.goTo();
@@ -86,8 +86,8 @@ test.describe('multiple apps running on localhost using different Clerk instance
8686
test('signing out from the root domains does not affect the sub domain', async ({ context }) => {
8787
const pages = await Promise.all([context.newPage(), context.newPage()]);
8888
const u = [
89-
createTestUtils({ app: apps[0].app, page: pages[0], context }),
90-
createTestUtils({ app: apps[1].app, page: pages[1], context }),
89+
createTestUtils({ app: apps[0].app, page: pages[0], context, useTestingToken: false }),
90+
createTestUtils({ app: apps[1].app, page: pages[1], context, useTestingToken: false }),
9191
];
9292

9393
// signin in tab0

integration/tests/localhost/localhost-different-port-same-instance.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ test.describe('multiple apps running on localhost using same Clerk instance @loc
3939
test('the cookies are aligned for the root and sub domains', async ({ context }) => {
4040
const pages = await Promise.all([context.newPage(), context.newPage()]);
4141
const u = [
42-
createTestUtils({ app: apps[0].app, page: pages[0], context }),
43-
createTestUtils({ app: apps[1].app, page: pages[1], context }),
42+
createTestUtils({ app: apps[0].app, page: pages[0], context, useTestingToken: false }),
43+
createTestUtils({ app: apps[1].app, page: pages[1], context, useTestingToken: false }),
4444
];
4545

4646
await u[0].po.signIn.goTo();
@@ -81,8 +81,8 @@ test.describe('multiple apps running on localhost using same Clerk instance @loc
8181
test('signing out from the root domain affects the sub domain', async ({ context }) => {
8282
const pages = await Promise.all([context.newPage(), context.newPage()]);
8383
const u = [
84-
createTestUtils({ app: apps[0].app, page: pages[0], context }),
85-
createTestUtils({ app: apps[1].app, page: pages[1], context }),
84+
createTestUtils({ app: apps[0].app, page: pages[0], context, useTestingToken: false }),
85+
createTestUtils({ app: apps[1].app, page: pages[1], context, useTestingToken: false }),
8686
];
8787

8888
// sign tab0

integration/tests/localhost/localhost-switch-instance.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ test.describe('switching instances on localhost same port @localhost', () => {
2929
// Create app and user for the 1st app
3030
const { app } = await prepareApplication('sessions-dev-1', port);
3131
let page = await context.newPage();
32-
let u = createTestUtils({ app, page, context });
32+
let u = createTestUtils({ app, page, context, useTestingToken: false });
3333
let fakeUser = u.services.users.createFakeUser();
3434
fakeUsers.push(fakeUser);
3535

@@ -46,7 +46,7 @@ test.describe('switching instances on localhost same port @localhost', () => {
4646
await app.dev({ port });
4747

4848
page = await context.newPage();
49-
u = createTestUtils({ app, page, context });
49+
u = createTestUtils({ app, page, context, useTestingToken: false });
5050
fakeUser = u.services.users.createFakeUser();
5151
fakeUsers.push(fakeUser);
5252
await u.services.users.createBapiUser(fakeUser);

integration/tests/next-account-portal/common.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type TestParams = {
1616
};
1717

1818
export const testSignIn = async ({ app, page, context, fakeUser }: TestParams) => {
19-
const u = createTestUtils({ app, page, context });
19+
const u = createTestUtils({ app, page, context, useTestingToken: false });
2020
// Begin in localhost
2121
await u.page.goToAppHome();
2222
await u.page.waitForClerkJsLoaded();
@@ -79,7 +79,7 @@ export const testSignIn = async ({ app, page, context, fakeUser }: TestParams) =
7979
};
8080

8181
export const testSignUp = async ({ app, page, context }: TestParams) => {
82-
const u = createTestUtils({ app, page, context });
82+
const u = createTestUtils({ app, page, context, useTestingToken: false });
8383
const tempUser = u.services.users.createFakeUser({ fictionalEmail: true });
8484

8585
// Begin in localhost
@@ -148,7 +148,7 @@ export const testSignUp = async ({ app, page, context }: TestParams) => {
148148
};
149149

150150
export const testSSR = async ({ app, page, context, fakeUser }: TestParams) => {
151-
const u = createTestUtils({ app, page, context });
151+
const u = createTestUtils({ app, page, context, useTestingToken: false });
152152

153153
// Begin in localhost
154154
await u.page.goToAppHome();

integration/tests/non-secure-context.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ testAgainstRunningApps({ withPattern: ['next.appRouter.withEmailCodes'] })(
5353

5454
test('sign-in flow', async ({ page }) => {
5555
const u = createTestUtils({ app, page });
56+
57+
await u.po.testingToken.setup();
5658
await u.page.goto(`http://${APP_HOST}`, { timeout: 50000 });
5759
await u.po.signIn.goTo();
5860
await u.po.signIn.signInWithEmailAndInstantPassword(fakeUser);

integration/tests/resiliency.test.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('resilienc
8181
await u.po.expect.toBeSignedIn();
8282
});
8383

84-
test('resiliency to not break devBroswer - dummy client and is not created on `/client` 4xx errors', async ({
84+
test('resiliency to not break devBrowser - dummy client and is not created on `/client` 4xx errors', async ({
8585
page,
8686
context,
8787
}) => {
@@ -100,6 +100,9 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('resilienc
100100
clerk_trace_id: 'some-trace-id',
101101
}),
102102
};
103+
104+
const u = createTestUtils({ app, page, context, useTestingToken: false });
105+
103106
await page.route('**/v1/client?**', route => {
104107
return route.fulfill(response);
105108
});
@@ -108,8 +111,6 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('resilienc
108111
return route.fulfill(response);
109112
});
110113

111-
const u = createTestUtils({ app, page, context });
112-
113114
const waitForClientImmediately = page.waitForResponse(
114115
response => response.url().includes('/client?') && response.status() === 401,
115116
{ timeout: 3_000 },

integration/tests/restricted-mode.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ export default function Page() {
116116

117117
const invitation = await u.services.invitations.createBapiInvitation(invitedUser.email);
118118

119+
await u.po.testingToken.setup();
119120
await u.page.goto(invitation.url);
120121
await u.po.signUp.waitForMounted();
121122
await expect(u.page.getByText(/Create your account/i).first()).toBeVisible();

integration/tests/sessions/prod-app-migration.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ test.describe('root and subdomain production apps @manual-run', () => {
5858
fakeUsers.push(fakeUser);
5959
await u.services.users.createBapiUser(fakeUser);
6060

61+
await u.po.testingToken.setup();
6162
await u.page.goto(`https://${host}`);
6263
await u.po.signIn.goTo({ timeout: 30000 });
6364
await u.po.signIn.signInWithEmailAndInstantPassword(fakeUser);

0 commit comments

Comments
 (0)