Skip to content

Commit d690fa9

Browse files
authored
Merge pull request #279 from Programcode/fix/browser-nightly-main
Restore Browser nightly coverage after UI and API changes
2 parents 151842f + fc39149 commit d690fa9

7 files changed

Lines changed: 42 additions & 24 deletions

‎e2e/home-navigation.spec.ts‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ test('onboarding keeps its original start schedule after a delayed lazy chunk',
8787
await expect(page.locator('.react-joyride__tooltip')).toBeVisible({ timeout: 15_000 });
8888
});
8989

90-
test('onboarding starts a fresh delay when a protected route reaches home', async ({ page }) => {
90+
test('onboarding stays closed on a protected tool and starts when it reaches home', async ({ page }) => {
91+
await page.clock.install();
9192
await page.addInitScript(() => {
9293
window.localStorage.setItem('debate-trainer-onboarding', JSON.stringify({
9394
state: { hasCompletedOnboarding: false, isTourRunning: false },
@@ -96,12 +97,14 @@ test('onboarding starts a fresh delay when a protected route reaches home', asyn
9697
});
9798
await page.goto('/app/generate', { waitUntil: 'domcontentloaded' });
9899
await expect(page.getByRole('heading', { name: 'Your case will appear here' })).toBeVisible({ timeout: 15_000 });
99-
// eslint-disable-next-line no-restricted-properties -- observation window: let the first onboarding delay run partway before navigating.
100-
await page.waitForTimeout(650);
100+
// Advance past the tour's 500ms deadline while still on the tool. The tour
101+
// now starts when its Home target exists, rather than after a fixed delay.
102+
await page.clock.runFor(1_000);
103+
await expect(page.locator('.react-joyride__tooltip')).toHaveCount(0);
101104

102105
await page.locator('header a[href="/app"]').first().click();
103106
await expect(page).toHaveURL(/\/app$/);
104-
await expect(page.locator('.react-joyride__tooltip')).toHaveCount(0, { timeout: 100 });
107+
await expect(page.locator('[data-tour="current-debate"]')).toBeVisible();
105108
await expect(page.locator('.react-joyride__tooltip')).toBeVisible({ timeout: 15_000 });
106109
});
107110

‎e2e/hungarian-parity.spec.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ test.describe('Hungarian parity', () => {
3636

3737
await expectHungarianDocument(page);
3838
await expect(page.getByRole('heading', { level: 1, name: `${site.product}: MI-alapú vitafelkészítés és gyakorlás` })).toBeVisible();
39-
await expect(page.getByText(/^Attól függ, mire van szükséged\. 2026\. október állapot szerint/)).toBeAttached();
39+
await expect(page.locator('#short-answer-text')).toContainText('Egy konkrét indítványra készülve');
4040
if ((page.viewportSize()?.width ?? 0) < 768) {
4141
await expect(page.getByRole('button', { name: 'Menü megnyitása' })).toBeVisible();
4242
} else {

‎e2e/loading-performance.spec.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ test('authenticated routes keep the shell and current page after refresh', async
7070
] as const) {
7171
await page.goto(path);
7272
await page.reload();
73-
await expect(page.locator('header')).toBeVisible();
73+
await expect(page.getByRole('banner')).toBeVisible();
7474
await expect(page.getByRole('heading', { name: heading, exact: true })).toBeVisible();
7575
await expect(page.getByText('DebateOwl is the official')).toHaveCount(0);
7676
}

‎e2e/localization.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ test('sign-in and not-found pages carry the language switcher', async ({ page })
110110
await shot(page, '02-login-hu');
111111

112112
await page.goto('/no-such-page');
113-
await expect(page.getByRole('heading', { level: 1, name: hu.notFound.title })).toBeVisible();
113+
await expect(page.getByRole('heading', { level: 1, name: hu.notFound.message })).toBeVisible();
114114
await expect(page).toHaveTitle(brand(hu.pageHead.notFound.title));
115115
await shot(page, '03-not-found-hu');
116116
await choose(page, 'es');
117117
await expect(page).toHaveTitle(brand(es.pageHead.notFound.title));
118-
await expect(page.getByText(es.notFound.message)).toBeVisible();
118+
await expect(page.getByRole('heading', { level: 1, name: es.notFound.message })).toBeVisible();
119119
await shot(page, '04-not-found-es');
120120
});
121121

‎e2e/navigation-performance.spec.ts‎

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ test('workspaces stay unavailable without a collaboration endpoint', async ({ pa
9494

9595
await expect(page.locator('a[href="/app/workspaces"]')).toHaveCount(0);
9696
await page.goto('/app/workspaces', { waitUntil: 'domcontentloaded' });
97-
await expect(page.getByRole('heading', { name: '404' })).toBeVisible();
97+
await expect(page.getByText('404', { exact: true })).toBeVisible();
98+
await expect(page.getByRole('heading', { level: 1, name: 'Page not found' })).toBeVisible();
9899
});
99100

100101
test('a delayed public route keeps the main landmark', async ({ page }) => {
@@ -177,7 +178,9 @@ test('a failed route chunk recovers after the offered reload', async ({ page })
177178
let attempts = 0;
178179
await page.route('**/src/pages/AttackPage.tsx*', async (route) => {
179180
attempts += 1;
180-
if (attempts === 1) {
181+
// The first failure reloads automatically. Fail that retry too, so the
182+
// boundary offers its manual Reload action instead of recovering first.
183+
if (attempts <= 2) {
181184
await route.fulfill({ status: 503, contentType: 'text/plain', body: 'chunk unavailable' });
182185
return;
183186
}
@@ -190,8 +193,9 @@ test('a failed route chunk recovers after the offered reload', async ({ page })
190193
await homeToolLink(page, 'attack').click();
191194

192195
await expect(page.getByRole('heading', { name: 'Unable to load this page' })).toBeVisible();
196+
expect(attempts).toBe(2);
193197
await page.getByRole('button', { name: 'Reload' }).click();
194-
await expect.poll(() => attempts).toBe(2);
198+
await expect.poll(() => attempts).toBe(3);
195199
await waitForContent(page, attackContent);
196200
await expect(page.getByRole('banner')).toBeVisible();
197201
});
@@ -365,14 +369,23 @@ test('subscription reads stay cached across sibling tool routes', async ({ page
365369
await route.fulfill({ json: { announcements: [] } });
366370
return;
367371
}
372+
if (url.pathname.endsWith('/rest/v1/rpc/ai_usage_today')) {
373+
subscriptionRequests.push('ai_usage_today');
374+
await route.fulfill({ json: 0 });
375+
return;
376+
}
368377
if (url.pathname.includes('/rest/v1/')) {
369378
const select = url.searchParams.get('select') ?? '';
370379
if (url.pathname.endsWith('/user_settings') && select.includes('subscription_tier')) {
371380
subscriptionRequests.push('user_settings');
372381
} else if (url.pathname.endsWith('/subscriptions')) {
373382
subscriptionRequests.push('subscriptions');
374-
} else if (url.pathname.endsWith('/ai_requests')) {
375-
subscriptionRequests.push('ai_requests');
383+
}
384+
// An empty single-row read is a PostgREST error, not a truthy array.
385+
// Otherwise settings hydration treats [] as an account and reads billing.
386+
if ((route.request().headers().accept ?? '').includes('vnd.pgrst.object')) {
387+
await route.fulfill({ status: 406, json: { code: 'PGRST116', message: 'No rows returned' } });
388+
return;
376389
}
377390
await route.fulfill({
378391
status: 200,
@@ -387,13 +400,13 @@ test('subscription reads stay cached across sibling tool routes', async ({ page
387400

388401
await page.goto('/app/generate');
389402
await waitForContent(page, { selector: 'main h1', text: 'Generate' });
390-
await expect.poll(() => subscriptionRequests.filter((name) => name === 'ai_requests').length).toBe(1);
403+
await expect.poll(() => subscriptionRequests.filter((name) => name === 'ai_usage_today').length).toBe(1);
391404

392405
await openHome(page);
393406
await homeToolLink(page, 'attack').click();
394407
await waitForContent(page, attackContent);
395408
// eslint-disable-next-line no-restricted-properties -- observation window: no extra subscription request may follow.
396409
await page.waitForTimeout(100);
397410

398-
expect(subscriptionRequests).toEqual(['user_settings', 'ai_requests']);
411+
expect(subscriptionRequests).toEqual(['user_settings', 'ai_usage_today']);
399412
});

‎e2e/quality-backlog.spec.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ test('Flowchart deletes a selected node at once and Undo puts it back', async ({
9191
await page.getByText('Argument 1', { exact: true }).click();
9292
const remove = page.getByRole('button', { name: 'Delete' }).last();
9393
if (testInfo.project.name === 'mobile-chromium') {
94-
const box = await remove.boundingBox();
95-
expect(box).not.toBeNull();
96-
await page.touchscreen.tap(box!.x + box!.width / 2, box!.y + box!.height / 2);
94+
// Locator taps scroll into view and wait for layout stability, just like
95+
// clicks. Raw viewport coordinates can hit the canvas after selection reflows.
96+
await remove.tap();
9797
} else {
9898
await remove.click();
9999
}

‎e2e/search-quality.spec.ts‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,13 @@ test('authenticated Factoids shows the consulted-source quality panel', async ({
8080
await page.getByRole('textbox', { name: /statement/i }).fill('Solar energy costs are falling');
8181
await page.getByRole('button', { name: /find factoids/i }).click();
8282

83-
await expect(page.getByRole('heading', { name: /researched sources/i })).toBeVisible();
84-
await expect(page.getByRole('link', { name: /official energy statistics/i }).first()).toHaveAttribute('href', strongSourceUrl);
85-
await expect(page.getByRole('link', { name: /broad commentary/i })).toHaveAttribute('href', weakSourceUrl);
86-
await expect(page.getByText('Strong', { exact: true })).toBeVisible();
87-
await expect(page.getByText('Weak', { exact: true })).toBeVisible();
88-
await expect(page.getByText('fallback context only', { exact: true })).toBeVisible();
83+
const sources = page.locator('details').filter({ has: page.locator('summary', { hasText: 'Researched sources (2)' }) });
84+
await sources.locator('summary').click();
85+
await expect(sources).toHaveAttribute('open', '');
86+
await expect(sources.getByRole('link', { name: /official energy statistics/i })).toHaveAttribute('href', strongSourceUrl);
87+
await expect(sources.getByRole('link', { name: /broad commentary/i })).toHaveAttribute('href', weakSourceUrl);
88+
await expect(sources.getByText('Strong', { exact: true })).toBeVisible();
89+
await expect(sources.getByText('Weak', { exact: true })).toBeVisible();
90+
await expect(sources.getByText('fallback context only', { exact: true })).toBeVisible();
8991
await expect(page.getByText('Solar costs fell by 42 percent')).toBeVisible();
9092
});

0 commit comments

Comments
 (0)