Skip to content

Commit 9bcb786

Browse files
authoredMar 13, 2025
test(e2e): Adding tests for handling reverification for AIO components (#5338)
1 parent 3e8bfa2 commit 9bcb786

File tree

5 files changed

+194
-2
lines changed

5 files changed

+194
-2
lines changed
 

‎.changeset/mighty-falcons-fly.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

‎integration/testUtils/userVerificationPageObject.ts

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export const createUserVerificationComponentPageObject = (testArgs: TestArgs) =>
1313
waitForMounted: (selector = '.cl-userVerification-root') => {
1414
return page.waitForSelector(selector, { state: 'attached' });
1515
},
16+
waitForClosed: (selector = '.cl-userVerification-root') => {
17+
return page.waitForSelector(selector, { state: 'detached' });
18+
},
19+
closeReverificationModal: () => {
20+
return page.getByLabel('Close modal').click();
21+
},
1622
getUseAnotherMethodLink: () => {
1723
return page.getByRole('link', { name: /use another method/i });
1824
},

‎integration/testUtils/usersService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export type UserService = {
6363
* Allowing 10^5 combinations should be enough entropy for e2e purposes.
6464
* @see https://clerk.com/docs/testing/e2e-testing#phone-numbers
6565
*/
66-
function fakerPhoneNumber() {
66+
export function fakerPhoneNumber() {
6767
return `+1###55501##`.replace(/#+/g, m => faker.string.numeric(m.length));
6868
}
6969

‎integration/tests/reverification.test.ts

+168-1
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ import { expect, test } from '@playwright/test';
44
import { appConfigs } from '../presets';
55
import type { FakeOrganization, FakeUser } from '../testUtils';
66
import { createTestUtils, testAgainstRunningApps } from '../testUtils';
7+
import { stringPhoneNumber } from '../testUtils/phoneUtils';
8+
import { fakerPhoneNumber } from '../testUtils/usersService';
79

810
const utils = [
911
'action',
1012
// , 'route'
1113
];
1214
const capitalize = (type: string) => type[0].toUpperCase() + type.slice(1);
15+
1316
testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })(
14-
'@nextjs require re-verification',
17+
'@nextjs require @reverification',
1518
({ app }) => {
1619
test.describe.configure({ mode: 'parallel' });
1720

@@ -40,6 +43,170 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })(
4043
await app.teardown();
4144
});
4245

46+
test('reverification prompt on adding new email address', async ({ page, context }) => {
47+
const u = createTestUtils({ app, page, context });
48+
await u.po.signIn.goTo();
49+
await u.po.signIn.waitForMounted();
50+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeViewer.email, password: fakeViewer.password });
51+
await u.po.expect.toBeSignedIn();
52+
53+
await u.po.userProfile.goTo();
54+
await u.po.userProfile.waitForMounted();
55+
56+
await u.page.waitForFunction(async () => {
57+
await window.Clerk.session.startVerification({
58+
level: 'first_factor',
59+
});
60+
});
61+
62+
await u.po.userProfile.clickAddEmailAddress();
63+
await u.po.userProfile.waitForSectionCardOpened('emailAddresses');
64+
65+
const newFakeEmail = `new-${fakeViewer.email}`;
66+
await u.po.userProfile.typeEmailAddress(newFakeEmail);
67+
68+
await u.page.getByRole('button', { name: /^add$/i }).click();
69+
70+
await u.po.userVerification.waitForMounted();
71+
await u.po.userVerification.setPassword(fakeViewer.password);
72+
await u.po.userVerification.continue();
73+
await u.po.userVerification.waitForClosed();
74+
75+
await u.po.userProfile.enterTestOtpCode();
76+
77+
await expect(
78+
u.page.locator('.cl-profileSectionItem__emailAddresses').filter({
79+
hasText: newFakeEmail,
80+
}),
81+
).toContainText(newFakeEmail);
82+
});
83+
84+
test('reverification prompt on adding new phone number', async ({ page, context }) => {
85+
const u = createTestUtils({ app, page, context });
86+
await u.po.signIn.goTo();
87+
await u.po.signIn.waitForMounted();
88+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeViewer.email, password: fakeViewer.password });
89+
await u.po.expect.toBeSignedIn();
90+
91+
await u.po.userProfile.goTo();
92+
await u.po.userProfile.waitForMounted();
93+
94+
await u.page.waitForFunction(async () => {
95+
await window.Clerk.session.startVerification({
96+
level: 'first_factor',
97+
});
98+
});
99+
100+
await u.po.userProfile.clickAddPhoneNumber();
101+
await u.po.userProfile.waitForSectionCardOpened('phoneNumbers');
102+
const newFakePhoneNumber = fakerPhoneNumber();
103+
104+
await u.po.userProfile.typePhoneNumber(newFakePhoneNumber);
105+
106+
await u.page.getByRole('button', { name: /^add$/i }).click();
107+
108+
await u.po.userVerification.waitForMounted();
109+
110+
await u.po.userVerification.setPassword(fakeViewer.password);
111+
await u.po.userVerification.continue();
112+
113+
await u.po.userVerification.waitForClosed();
114+
115+
await u.po.userProfile.enterTestOtpCode();
116+
117+
const formatedPhoneNumber = stringPhoneNumber(newFakePhoneNumber);
118+
119+
await expect(u.page.locator('.cl-profileSectionItem__phoneNumbers')).toContainText(formatedPhoneNumber);
120+
});
121+
122+
test('reverification prompt can be cancelled when adding email', async ({ page, context }) => {
123+
const u = createTestUtils({ app, page, context });
124+
await u.po.signIn.goTo();
125+
await u.po.signIn.waitForMounted();
126+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeViewer.email, password: fakeViewer.password });
127+
await u.po.expect.toBeSignedIn();
128+
129+
await u.po.userProfile.goTo();
130+
await u.po.userProfile.waitForMounted();
131+
132+
await u.page.waitForFunction(async () => {
133+
await window.Clerk.session.startVerification({
134+
level: 'first_factor',
135+
});
136+
});
137+
138+
await u.po.userProfile.clickAddEmailAddress();
139+
await u.po.userProfile.waitForSectionCardOpened('emailAddresses');
140+
141+
const newFakeEmail = `new2-${fakeViewer.email}`;
142+
await u.po.userProfile.typeEmailAddress(newFakeEmail);
143+
144+
await u.page.getByRole('button', { name: /^add$/i }).click();
145+
146+
await u.po.userVerification.waitForMounted();
147+
148+
await u.po.userVerification.closeReverificationModal();
149+
150+
await u.po.userVerification.waitForClosed();
151+
await u.po.userProfile.enterTestOtpCode();
152+
153+
await expect(u.page.locator('.cl-profileSectionItem__emailAddresses')).not.toContainText(newFakeEmail);
154+
});
155+
156+
test('reverification propmt when deleting account', async ({ page, context }) => {
157+
const u = createTestUtils({ app, page, context });
158+
const delFakeUser = u.services.users.createFakeUser({
159+
withUsername: true,
160+
fictionalEmail: true,
161+
withPhoneNumber: true,
162+
});
163+
const bapiFakeUser = await u.services.users.createBapiUser({
164+
...delFakeUser,
165+
username: undefined,
166+
phoneNumber: undefined,
167+
});
168+
169+
await u.po.signIn.goTo();
170+
await u.po.signIn.waitForMounted();
171+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: delFakeUser.email, password: delFakeUser.password });
172+
await u.po.expect.toBeSignedIn();
173+
174+
await u.po.userProfile.goTo();
175+
await u.po.userProfile.waitForMounted();
176+
await u.po.userProfile.switchToSecurityTab();
177+
178+
await u.page.waitForFunction(async () => {
179+
await window.Clerk.session.startVerification({
180+
level: 'first_factor',
181+
});
182+
});
183+
184+
await u.page
185+
.getByRole('button', {
186+
name: /delete account/i,
187+
})
188+
.click();
189+
190+
await u.page.locator('input[name=deleteConfirmation]').fill('Delete account');
191+
192+
await u.page.locator('form').getByRole('button', { name: 'Delete account' }).click();
193+
194+
await u.po.userVerification.waitForMounted();
195+
await u.po.userVerification.setPassword(delFakeUser.password);
196+
await u.po.userVerification.continue();
197+
await u.po.userVerification.waitForClosed();
198+
199+
await u.po.expect.toBeSignedOut();
200+
201+
await u.page.waitForAppUrl('/');
202+
203+
const sessionCookieList = (await u.page.context().cookies()).filter(cookie =>
204+
cookie.name.startsWith('__session'),
205+
);
206+
207+
expect(sessionCookieList.length).toBe(0);
208+
});
209+
43210
utils.forEach(type => {
44211
test(`reverification error from ${capitalize(type)}`, async ({ page, context }) => {
45212
test.setTimeout(270_000);

‎pnpm-lock.yaml

+17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)