From cc473626f6e7633bf7f30dcde6eaaec0095957c2 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Thu, 30 Jul 2026 12:38:17 -0700 Subject: [PATCH 1/3] fix(e2e): Stop relying on startVerification to reset fva in reverification tests --- integration/tests/reverification.test.ts | 41 +++++++++++++++++------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/integration/tests/reverification.test.ts b/integration/tests/reverification.test.ts index da72fa563d4..0a5e8127a13 100644 --- a/integration/tests/reverification.test.ts +++ b/integration/tests/reverification.test.ts @@ -231,13 +231,21 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect(u.page.getByText(/\{\s*"userId"\s*:\s*"user_[^"]+"\s*\}/i)).toBeVisible(); - // Hack to reset fva + // FAPI no longer resets fva when a verification starts (USER-5572), so wait + // for the signed-in factor to age past the action's afterMinutes threshold. await u.po.expect.toBeSignedIn(); - await page.evaluate(async () => { - return window.Clerk.session.startVerification({ - level: 'first_factor', - }); - }); + await page.waitForFunction( + async () => { + const token = await window.Clerk.session?.getToken({ skipCache: true }); + if (!token) { + return false; + } + const { fva } = JSON.parse(atob(token.split('.')[1])); + return Array.isArray(fva) && fva[0] >= 1; + }, + null, + { polling: 5_000, timeout: 120_000 }, + ); await u.page.goToRelative(`/requires-re-verification`); await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect( @@ -248,6 +256,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( }); test(`reverification recovery from ${capitalize(type)}`, async ({ page, context }) => { + test.setTimeout(270_000); const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); @@ -263,13 +272,21 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect(u.page.getByText(/\{\s*"userId"\s*:\s*"user_[^"]+"\s*\}/i)).toBeVisible(); - // Hack to reset fva + // FAPI no longer resets fva when a verification starts (USER-5572), so wait + // for the signed-in factor to age past the action's afterMinutes threshold. await u.po.expect.toBeSignedIn(); - await page.evaluate(async () => { - return window.Clerk.session.startVerification({ - level: 'first_factor', - }); - }); + await page.waitForFunction( + async () => { + const token = await window.Clerk.session?.getToken({ skipCache: true }); + if (!token) { + return false; + } + const { fva } = JSON.parse(atob(token.split('.')[1])); + return Array.isArray(fva) && fva[0] >= 1; + }, + null, + { polling: 5_000, timeout: 120_000 }, + ); await u.page.goToRelative(`/action-with-use-reverification`); await u.po.expect.toBeSignedIn(); From fc399462b135411aede8190a2b4fb1773fdb2b72 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Thu, 30 Jul 2026 12:42:38 -0700 Subject: [PATCH 2/3] chore: use poll method instead of waitForFunction --- integration/tests/reverification.test.ts | 62 +++++++++++++----------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/integration/tests/reverification.test.ts b/integration/tests/reverification.test.ts index 0a5e8127a13..d0ebaba3893 100644 --- a/integration/tests/reverification.test.ts +++ b/integration/tests/reverification.test.ts @@ -231,21 +231,24 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect(u.page.getByText(/\{\s*"userId"\s*:\s*"user_[^"]+"\s*\}/i)).toBeVisible(); - // FAPI no longer resets fva when a verification starts (USER-5572), so wait - // for the signed-in factor to age past the action's afterMinutes threshold. + // Starting a verification no longer resets fva server-side, so wait for the + // signed-in factor to age past the action's afterMinutes threshold. await u.po.expect.toBeSignedIn(); - await page.waitForFunction( - async () => { - const token = await window.Clerk.session?.getToken({ skipCache: true }); - if (!token) { - return false; - } - const { fva } = JSON.parse(atob(token.split('.')[1])); - return Array.isArray(fva) && fva[0] >= 1; - }, - null, - { polling: 5_000, timeout: 120_000 }, - ); + await expect + .poll( + () => + page.evaluate(async () => { + const token = await window.Clerk.session?.getToken({ skipCache: true }); + if (!token) { + return -1; + } + const payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'); + const { fva } = JSON.parse(atob(payload)); + return Array.isArray(fva) ? fva[0] : -1; + }), + { intervals: [5_000], timeout: 120_000 }, + ) + .toBeGreaterThanOrEqual(1); await u.page.goToRelative(`/requires-re-verification`); await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect( @@ -272,21 +275,24 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect(u.page.getByText(/\{\s*"userId"\s*:\s*"user_[^"]+"\s*\}/i)).toBeVisible(); - // FAPI no longer resets fva when a verification starts (USER-5572), so wait - // for the signed-in factor to age past the action's afterMinutes threshold. + // Starting a verification no longer resets fva server-side, so wait for the + // signed-in factor to age past the action's afterMinutes threshold. await u.po.expect.toBeSignedIn(); - await page.waitForFunction( - async () => { - const token = await window.Clerk.session?.getToken({ skipCache: true }); - if (!token) { - return false; - } - const { fva } = JSON.parse(atob(token.split('.')[1])); - return Array.isArray(fva) && fva[0] >= 1; - }, - null, - { polling: 5_000, timeout: 120_000 }, - ); + await expect + .poll( + () => + page.evaluate(async () => { + const token = await window.Clerk.session?.getToken({ skipCache: true }); + if (!token) { + return -1; + } + const payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'); + const { fva } = JSON.parse(atob(payload)); + return Array.isArray(fva) ? fva[0] : -1; + }), + { intervals: [5_000], timeout: 120_000 }, + ) + .toBeGreaterThanOrEqual(1); await u.page.goToRelative(`/action-with-use-reverification`); await u.po.expect.toBeSignedIn(); From c58c75180b4ecddbab0e9c559d3282cc15973971 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Thu, 30 Jul 2026 12:43:21 -0700 Subject: [PATCH 3/3] chore: clean up --- integration/tests/reverification.test.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/integration/tests/reverification.test.ts b/integration/tests/reverification.test.ts index d0ebaba3893..3b41897be81 100644 --- a/integration/tests/reverification.test.ts +++ b/integration/tests/reverification.test.ts @@ -231,8 +231,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect(u.page.getByText(/\{\s*"userId"\s*:\s*"user_[^"]+"\s*\}/i)).toBeVisible(); - // Starting a verification no longer resets fva server-side, so wait for the - // signed-in factor to age past the action's afterMinutes threshold. + // startVerification no longer resets fva server-side, so age the signed-in factor past afterMinutes await u.po.expect.toBeSignedIn(); await expect .poll( @@ -243,8 +242,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( return -1; } const payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'); - const { fva } = JSON.parse(atob(payload)); - return Array.isArray(fva) ? fva[0] : -1; + return JSON.parse(atob(payload)).fva?.[0] ?? -1; }), { intervals: [5_000], timeout: 120_000 }, ) @@ -275,8 +273,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( await u.page.getByRole('button', { name: /LogUserId/i }).click(); await expect(u.page.getByText(/\{\s*"userId"\s*:\s*"user_[^"]+"\s*\}/i)).toBeVisible(); - // Starting a verification no longer resets fva server-side, so wait for the - // signed-in factor to age past the action's afterMinutes threshold. + // startVerification no longer resets fva server-side, so age the signed-in factor past afterMinutes await u.po.expect.toBeSignedIn(); await expect .poll( @@ -287,8 +284,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withReverification] })( return -1; } const payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'); - const { fva } = JSON.parse(atob(payload)); - return Array.isArray(fva) ? fva[0] : -1; + return JSON.parse(atob(payload)).fva?.[0] ?? -1; }), { intervals: [5_000], timeout: 120_000 }, )