Skip to content

Commit e3ca78e

Browse files
committed
made login tests more robust to timing issues
1 parent ec31bdf commit e3ca78e

File tree

5 files changed

+61
-36
lines changed

5 files changed

+61
-36
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ jobs:
5454
run: npm run lint
5555
- name: Build Next.js application
5656
run: npm run build
57-
- name: Install wait-on
58-
run: npm install --save-dev wait-on
5957
- name: Start the app
6058
run: npm start &
6159
- name: Wait for Next.js server to be ready

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,4 @@ package-lock.json
5656
/blob-report/
5757
/playwright/.cache/
5858
/playwright/.auth/
59+
tests/playwright-auth-sessions/

tests/admin-pages.spec.ts

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,45 @@ test('test access to admin page', async ({ getUserPage }) => {
55
// Call the getUserPage fixture with admin signin info to get authenticated session for admin
66
const adminPage = await getUserPage('admin@foo.com', 'changeme');
77

8-
// Navigate to the home adminPage
8+
// Navigate to the home page and wait for post-login indicator
99
await adminPage.goto('http://localhost:3000/');
10-
10+
await expect(
11+
adminPage.getByRole('button', { name: 'admin@foo.com' })
12+
).toBeVisible({ timeout: 10000 });
13+
1114
// Check for navigation elements
12-
await expect(adminPage.getByRole('link', { name: 'Next.js Application Template' })).toBeVisible();
13-
await expect(adminPage.getByRole('link', { name: 'Add Stuff' })).toBeVisible();
14-
await expect(adminPage.getByRole('link', { name: 'List Stuff' })).toBeVisible();
15-
await expect(adminPage.getByRole('link', { name: 'Admin' })).toBeVisible();
16-
await expect(adminPage.getByRole('button', { name: 'admin@foo.com' })).toBeVisible();
17-
15+
await expect(
16+
adminPage.getByRole('link', { name: 'Next.js Application Template' })
17+
).toBeVisible({ timeout: 5000 });
18+
await expect(
19+
adminPage.getByRole('link', { name: 'Add Stuff' })
20+
).toBeVisible({ timeout: 5000 });
21+
await expect(
22+
adminPage.getByRole('link', { name: 'List Stuff' })
23+
).toBeVisible({ timeout: 5000 });
24+
await expect(
25+
adminPage.getByRole('link', { name: 'Admin' })
26+
).toBeVisible({ timeout: 5000 });
27+
1828
// Test Add Stuff adminPage
1929
await adminPage.getByRole('link', { name: 'Add Stuff' }).click();
20-
await expect(adminPage.getByRole('heading', { name: 'Add Stuff' })).toBeVisible();
21-
30+
await expect(
31+
adminPage.getByRole('heading', { name: 'Add Stuff' })
32+
).toBeVisible({ timeout: 5000 });
33+
2234
// Test List Stuff adminPage
2335
await adminPage.getByRole('link', { name: 'List Stuff' }).click();
24-
await expect(adminPage.getByRole('heading', { name: 'Stuff' })).toBeVisible();
25-
36+
await expect(
37+
adminPage.getByRole('heading', { name: 'Stuff' })
38+
).toBeVisible({ timeout: 5000 });
39+
2640
// Test Admin adminPage
2741
await adminPage.getByRole('link', { name: 'Admin' }).click();
28-
await expect(adminPage.getByRole('heading', { name: 'List Stuff Admin' })).toBeVisible();
29-
await expect(adminPage.getByRole('heading', { name: 'List Users Admin' })).toBeVisible();
42+
await expect(
43+
adminPage.getByRole('heading', { name: 'List Stuff Admin' })
44+
).toBeVisible({ timeout: 5000 });
45+
await expect(
46+
adminPage.getByRole('heading', { name: 'List Users Admin' })
47+
).toBeVisible({ timeout: 5000 });
3048

3149
});

tests/auth-utils.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,14 @@ async function authenticateWithUI(
8484
await submitButton.click();
8585
}
8686

87-
// Wait for navigation to complete
88-
await page.waitForLoadState('networkidle');
89-
90-
// Verify authentication was successful
91-
await expect(async () => {
92-
const authState = await Promise.race([
93-
page.getByText(email).isVisible().then((visible) => ({ success: visible })),
94-
page.getByRole('button', { name: email }).isVisible().then((visible) => ({ success: visible })),
95-
page.getByText('Sign out').isVisible().then((visible) => ({ success: visible })),
96-
page.getByRole('button', { name: 'Sign out' }).isVisible().then((visible) => ({ success: visible })),
97-
new Promise<{ success: boolean }>((resolve) => setTimeout(() => resolve({ success: false }), 5000)),
98-
]);
9987

100-
expect(authState.success).toBeTruthy();
101-
}).toPass({ timeout: 10000 });
88+
// Wait for a clear post-login indicator (user button or sign out button)
89+
const userButton = page.getByRole('button', { name: email });
90+
const signOutButton = page.getByRole('button', { name: /sign out/i });
91+
await Promise.any([
92+
expect(userButton).toBeVisible({ timeout: 10000 }),
93+
expect(signOutButton).toBeVisible({ timeout: 10000 })
94+
]);
10295

10396
// Save session for future tests
10497
const cookies = await page.context().cookies();

tests/john-pages.spec.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,32 @@ import { test, expect } from './auth-utils';
22

33
test.slow();
44
test('can authenticate a specific user', async ({ getUserPage }) => {
5+
56
// Call the getUserPage fixture with users signin info to get authenticated session for user
67
const customUserPage = await getUserPage('john@foo.com', 'changeme');
78

8-
// Navigate to the home customUserPage
9+
// Navigate to the home page and wait for post-login indicator
910
await customUserPage.goto('http://localhost:3000/');
10-
await expect(customUserPage.getByRole('link', { name: 'Add Stuff' })).toBeVisible();
11-
await expect(customUserPage.getByRole('link', { name: 'List Stuff' })).toBeVisible();
12-
await expect(customUserPage.getByRole('button', { name: 'john@foo.com' })).toBeVisible();
11+
await expect(
12+
customUserPage.getByRole('button', { name: 'john@foo.com' })
13+
).toBeVisible({ timeout: 10000 });
14+
15+
// Now check for navigation links and headings
16+
await expect(
17+
customUserPage.getByRole('link', { name: 'Add Stuff' })
18+
).toBeVisible({ timeout: 5000 });
19+
await expect(
20+
customUserPage.getByRole('link', { name: 'List Stuff' })
21+
).toBeVisible({ timeout: 5000 });
22+
1323
await customUserPage.getByRole('link', { name: 'Add Stuff' }).click();
14-
await expect(customUserPage.getByRole('heading', { name: 'Add Stuff' })).toBeVisible();
24+
await expect(
25+
customUserPage.getByRole('heading', { name: 'Add Stuff' })
26+
).toBeVisible({ timeout: 5000 });
27+
1528
await customUserPage.getByRole('link', { name: 'List Stuff' }).click();
16-
await expect(customUserPage.getByRole('heading', { name: 'Stuff' })).toBeVisible();
29+
await expect(
30+
customUserPage.getByRole('heading', { name: 'Stuff' })
31+
).toBeVisible({ timeout: 5000 });
1732

1833
});

0 commit comments

Comments
 (0)