Skip to content

Commit 8c1382e

Browse files
committed
test(web): update auth-gate e2e specs for inline-retry token modal
The save flow no longer reloads — the dialog dismisses inline after the parked /api/* requests succeed on retry. Update the existing spec to match the new placeholder/button labels and 16-char minimum, and add two new specs covering the validation error and the second-401 inline error paths added in this PR. https://claude.ai/code/session_01WjsbdUtxDJZL3GaAvhyzav
1 parent 5efd88a commit 8c1382e

1 file changed

Lines changed: 38 additions & 5 deletions

File tree

app/packages/web/e2e/specs/auth-gate.spec.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { stubApis, ENV_DATA, COST_DATA } from '../fixtures/index.js';
33

44
/**
55
* Auth-gate specs use the base Playwright `test` (no pre-seeded token) so
6-
* they can verify the 401 → modal and token-save → reload flows in isolation.
6+
* they can verify the 401 → modal and token-save → inline-retry flows in
7+
* isolation.
78
*/
89

910
test.describe('auth gate', () => {
@@ -26,7 +27,7 @@ test.describe('auth gate', () => {
2627
await expect(page.getByRole('heading', { name: 'API token required' })).not.toBeVisible();
2728
});
2829

29-
test('should save token and show dashboard after reload', async ({ page }) => {
30+
test('should save token and dismiss modal without reloading', async ({ page }) => {
3031
// Playwright matches routes in REVERSE registration order, so register the
3132
// catch-all 404 FIRST and the specific 401/200 handlers after — otherwise
3233
// the catch-all takes precedence and the modal never triggers.
@@ -62,11 +63,43 @@ test.describe('auth gate', () => {
6263
await page.goto('/');
6364
await expect(page.getByRole('heading', { name: 'API token required' })).toBeVisible();
6465

65-
await page.getByPlaceholder('API token').fill('my-test-token');
66-
await page.getByRole('button', { name: 'Save & reload' }).click();
66+
// Inline validation requires ≥16 chars, no whitespace.
67+
await page.getByPlaceholder('Paste API token').fill('my-test-token-12345');
68+
await page.getByRole('button', { name: 'Save', exact: true }).click();
6769

68-
// After reload the stored token is sent; the modal must be gone.
70+
// Modal dismisses inline (no reload) and the dashboard surfaces.
6971
await expect(page.getByRole('heading', { name: 'Game Server Manager' })).toBeVisible();
7072
await expect(page.getByRole('heading', { name: 'API token required' })).not.toBeVisible();
7173
});
74+
75+
test('should show inline validation error for a too-short token', async ({ page }) => {
76+
await page.route('**/api/**', (route) =>
77+
route.fulfill({ status: 401, body: 'Unauthorized' })
78+
);
79+
await page.goto('/');
80+
await expect(page.getByRole('heading', { name: 'API token required' })).toBeVisible();
81+
82+
await page.getByPlaceholder('Paste API token').fill('short');
83+
await page.getByRole('button', { name: 'Save', exact: true }).click();
84+
85+
await expect(page.getByText(/at least 16 characters/i)).toBeVisible();
86+
// Modal stays open — validation never reached the network.
87+
await expect(page.getByRole('heading', { name: 'API token required' })).toBeVisible();
88+
});
89+
90+
test('should show inline server error when retry returns 401 again', async ({ page }) => {
91+
await page.route('**/api/**', (route) =>
92+
route.fulfill({ status: 401, body: 'Unauthorized' })
93+
);
94+
await page.goto('/');
95+
await expect(page.getByRole('heading', { name: 'API token required' })).toBeVisible();
96+
97+
await page.getByPlaceholder('Paste API token').fill('still-the-wrong-token-1234');
98+
await page.getByRole('button', { name: 'Save', exact: true }).click();
99+
100+
await expect(
101+
page.getByText(/Invalid token check `app\/server_config\.json` or `API_TOKEN`\./i),
102+
).toBeVisible();
103+
await expect(page.getByRole('heading', { name: 'API token required' })).toBeVisible();
104+
});
72105
});

0 commit comments

Comments
 (0)