Skip to content

Commit 658d8d8

Browse files
fix: unstable test
1 parent 3a6f18e commit 658d8d8

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

test/source/tests/page-recipe/oauth-page-recipe.ts

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,42 @@ import { Url } from '../../core/common';
99
export class OauthPageRecipe extends PageRecipe {
1010
private static longTimeout = 40;
1111

12+
/**
13+
* Check if an error is a "Navigating frame was detached" error.
14+
* This can happen when the OAuth page closes during navigation (e.g., successful auth).
15+
* @param e - The error to check
16+
* @returns true if this is a frame detached error that can be safely ignored
17+
*/
18+
private static isFrameDetachedError(e: unknown): boolean {
19+
if (!e) {
20+
return false;
21+
}
22+
// Check if it's an Error object with a message property
23+
if (e instanceof Error) {
24+
return e.message.includes('Navigating frame was detached');
25+
}
26+
// Fallback: convert to string and check (for non-Error objects)
27+
const errorStr = String(e);
28+
return errorStr.includes('Navigating frame was detached') || errorStr.includes('frame was detached');
29+
}
30+
31+
/**
32+
* Safely navigate to a URL, ignoring "frame was detached" errors.
33+
* The OAuth page may close during navigation on successful auth.
34+
* @param oauthPage - The OAuth page to navigate
35+
* @param url - The URL to navigate to
36+
*/
37+
private static async safeGoto(oauthPage: ControllablePage, url: string): Promise<void> {
38+
try {
39+
await oauthPage.target.goto(url);
40+
} catch (e: unknown) {
41+
if (!OauthPageRecipe.isFrameDetachedError(e)) {
42+
throw e;
43+
}
44+
// Ignore frame detached errors - page closed successfully
45+
}
46+
}
47+
1248
public static mock = async (
1349
t: AvaContext,
1450
oauthPage: ControllablePage,
@@ -21,33 +57,28 @@ export class OauthPageRecipe extends PageRecipe {
2157
await oauthPage.close();
2258
} else if (action === 'login_with_invalid_state') {
2359
mockOauthUrl = Url.removeParamsFromUrl(mockOauthUrl, ['login_hint']);
24-
await oauthPage.target.goto(
60+
await OauthPageRecipe.safeGoto(
61+
oauthPage,
2562
mockOauthUrl.replace('CRYPTUP_STATE', 'INVALID_CRYPTUP_STATE') + '&login_hint=' + encodeURIComponent(acctEmail) + '&proceed=true'
2663
);
2764
} else if (action === 'missing_permission') {
2865
mockOauthUrl = Url.removeParamsFromUrl(mockOauthUrl, ['scope']);
2966
mockOauthUrl += '&scope=missing_scope';
30-
await oauthPage.target.goto(mockOauthUrl + '&proceed=true');
67+
await OauthPageRecipe.safeGoto(oauthPage, mockOauthUrl + '&proceed=true');
3168
} else if (!login_hint) {
32-
await oauthPage.target.goto(mockOauthUrl + '&login_hint=' + encodeURIComponent(acctEmail) + '&proceed=true');
69+
await OauthPageRecipe.safeGoto(oauthPage, mockOauthUrl + '&login_hint=' + encodeURIComponent(acctEmail) + '&proceed=true');
3370
} else {
3471
if (action === 'override_acct') {
3572
mockOauthUrl = Url.removeParamsFromUrl(mockOauthUrl, ['login_hint']);
3673
mockOauthUrl += '&login_hint=' + encodeURIComponent(acctEmail);
3774
}
38-
await oauthPage.target.goto(mockOauthUrl + '&proceed=true');
75+
await OauthPageRecipe.safeGoto(oauthPage, mockOauthUrl + '&proceed=true');
3976
}
4077
};
4178

4279
public static customIdp = async (t: AvaContext, oauthPage: ControllablePage): Promise<void> => {
4380
const mockOauthUrl = oauthPage.target.url();
44-
try {
45-
await oauthPage.target.goto(mockOauthUrl + '&proceed=true');
46-
} catch (e) {
47-
if (!e.message.includes('Navigating frame was detached')) {
48-
throw e;
49-
}
50-
}
81+
await OauthPageRecipe.safeGoto(oauthPage, mockOauthUrl + '&proceed=true');
5182
};
5283

5384
public static google = async (

0 commit comments

Comments
 (0)