diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be8f56457373..a8e35a53dc16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,6 +59,8 @@ jobs: - run: pnpm playwright install ${{ matrix.e2e-browser }} - run: pnpm run sync-all - run: pnpm test:kit + - name: Print flaky test report + run: node scripts/print-flaky-test-report.js - name: Archive test results if: failure() shell: bash @@ -115,6 +117,8 @@ jobs: - run: pnpm playwright install ${{ matrix.e2e-browser }} - run: pnpm run sync-all - run: pnpm test:cross-platform:${{ matrix.mode }} + - name: Print flaky test report + run: node scripts/print-flaky-test-report.js - name: Archive test results if: failure() shell: bash diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/+page.svelte index da9d1efb73e6..b9080af1f26c 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/+page.svelte @@ -11,5 +11,5 @@ } -
Count is {data.count}
+Count is {data.count}
diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/count/+server.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/count/+server.js index 999b7fd7cd0a..49c2e014b003 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/count/+server.js +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/count/+server.js @@ -1,8 +1,10 @@ import { json } from '@sveltejs/kit'; -import { count } from '../state.js'; -export function GET({ setHeaders }) { +export function GET({ setHeaders, cookies }) { setHeaders({ 'cache-control': 'public, max-age=4', age: '2' }); + + const count = +(cookies.get('cache-control-bust-count') ?? 0); + return json({ count }); } diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/increment/+server.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/increment/+server.js index 1ddf1e429013..2e30bdd1d9a4 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/increment/+server.js +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/increment/+server.js @@ -1,7 +1,11 @@ import { json } from '@sveltejs/kit'; -import { increment } from '../state.js'; -export function GET() { - increment(); +export function GET({ cookies }) { + cookies.set( + 'cache-control-bust-count', + +(cookies.get('cache-control-bust-count') ?? 0) + 1 + '', + { path: '/' } + ); + return json({}); } diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/state.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/state.js deleted file mode 100644 index ba1431d4079a..000000000000 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/bust/state.js +++ /dev/null @@ -1,9 +0,0 @@ -export let count = 0; - -export function increment() { - return count++; -} - -export function reset() { - count = 0; -} diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/+page.svelte index 3d51fd478570..ecd93c6ab44d 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/+page.svelte @@ -4,11 +4,14 @@ /** @type {import('./$types').PageData} */ export let data; + let ticker = 0; async function update() { + ticker += 1; await fetch('/load/cache-control/default/increment'); - invalidate('/load/cache-control/default/count'); + await invalidate('/load/cache-control/default/count'); + ticker += 1; } -Count is {data.count}
- +Count is {data.count}
+ diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/count/+server.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/count/+server.js index 999b7fd7cd0a..8579f6fc1ca7 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/count/+server.js +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/count/+server.js @@ -1,8 +1,10 @@ import { json } from '@sveltejs/kit'; -import { count } from '../state.js'; -export function GET({ setHeaders }) { +export function GET({ setHeaders, cookies }) { setHeaders({ 'cache-control': 'public, max-age=4', age: '2' }); + + const count = +(cookies.get('cache-control-default-count') ?? 0); + return json({ count }); } diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/increment/+server.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/increment/+server.js index 1ddf1e429013..0cd89b430a60 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/increment/+server.js +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/increment/+server.js @@ -1,7 +1,11 @@ import { json } from '@sveltejs/kit'; -import { increment } from '../state.js'; -export function GET() { - increment(); +export function GET({ cookies }) { + cookies.set( + 'cache-control-default-count', + +(cookies.get('cache-control-default-count') ?? 0) + 1 + '', + { path: '/' } + ); + return json({}); } diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/state.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/default/state.js deleted file mode 100644 index ba1431d4079a..000000000000 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/default/state.js +++ /dev/null @@ -1,9 +0,0 @@ -export let count = 0; - -export function increment() { - return count++; -} - -export function reset() { - count = 0; -} diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/+page.svelte index 1b03361eada3..f8b23481af7e 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/+page.svelte @@ -10,5 +10,5 @@ } -Count is {data.count}
+Count is {data.count}
diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/count/+server.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/count/+server.js index 999b7fd7cd0a..b321b0650907 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/count/+server.js +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/count/+server.js @@ -1,8 +1,10 @@ import { json } from '@sveltejs/kit'; -import { count } from '../state.js'; -export function GET({ setHeaders }) { +export function GET({ setHeaders, cookies }) { setHeaders({ 'cache-control': 'public, max-age=4', age: '2' }); + + const count = +(cookies.get('cache-control-force-count') ?? 0); + return json({ count }); } diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/increment/+server.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/increment/+server.js index 1ddf1e429013..fee0dacb14f2 100644 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/increment/+server.js +++ b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/increment/+server.js @@ -1,7 +1,11 @@ import { json } from '@sveltejs/kit'; -import { increment } from '../state.js'; -export function GET() { - increment(); +export function GET({ cookies }) { + cookies.set( + 'cache-control-force-count', + +(cookies.get('cache-control-force-count') ?? 0) + 1 + '', + { path: '/' } + ); + return json({}); } diff --git a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/state.js b/packages/kit/test/apps/basics/src/routes/load/cache-control/force/state.js deleted file mode 100644 index ba1431d4079a..000000000000 --- a/packages/kit/test/apps/basics/src/routes/load/cache-control/force/state.js +++ /dev/null @@ -1,9 +0,0 @@ -export let count = 0; - -export function increment() { - return count++; -} - -export function reset() { - count = 0; -} diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index 2d729e903adf..21693343dd4a 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -145,35 +145,41 @@ test.describe('Load', () => { }); test('load does not call fetch if max-age allows it', async ({ page }) => { - page.addInitScript(` + await page.addInitScript(` window.now = 0; window.performance.now = () => now; `); await page.goto('/load/cache-control/default'); - await expect(page.getByText('Count is 0')).toBeVisible(); - await page.locator('button').click(); - await page.waitForLoadState('networkidle'); - await expect(page.getByText('Count is 0')).toBeVisible(); - await page.evaluate(() => (window.now = 2500)); + const button = page.locator('button'); + const p = page.locator('p.counter'); - await page.locator('button').click(); - await expect(page.getByText('Count is 2')).toBeVisible(); + await button.click(); + await expect(button).toHaveAttribute('data-ticker', '2'); + await expect(p).toHaveText('Count is 0'); + + await page.evaluate('window.now = 2500'); + + await button.click(); + await expect(button).toHaveAttribute('data-ticker', '4'); + await expect(p).toHaveText('Count is 2'); }); test('load does ignore ttl if fetch cache options says so', async ({ page }) => { await page.goto('/load/cache-control/force'); - await expect(page.getByText('Count is 0')).toBeVisible(); + const p = page.locator('p.counter'); + await expect(p).toHaveText('Count is 0'); await page.locator('button').click(); - await expect(page.getByText('Count is 1')).toBeVisible(); + await expect(p).toHaveText('Count is 1'); }); test('load busts cache if non-GET request to resource is made', async ({ page }) => { await page.goto('/load/cache-control/bust'); - await expect(page.getByText('Count is 0')).toBeVisible(); + const p = page.locator('p.counter'); + await expect(p).toHaveText('Count is 0'); await page.locator('button').click(); - await expect(page.getByText('Count is 1')).toBeVisible(); + await expect(p).toHaveText('Count is 1'); }); test('__data.json has cache-control: private, no-store', async ({ page, clicknav }) => { diff --git a/packages/kit/test/apps/basics/test/cross-platform/client.test.js b/packages/kit/test/apps/basics/test/cross-platform/client.test.js index dfa97ce7f3be..5b3d1fa953f5 100644 --- a/packages/kit/test/apps/basics/test/cross-platform/client.test.js +++ b/packages/kit/test/apps/basics/test/cross-platform/client.test.js @@ -76,6 +76,7 @@ test.describe('a11y', () => { ).toBe(1); await clicknav('[href="/selection/b"]'); + expect( await page.evaluate(() => { const selection = getSelection(); @@ -98,7 +99,7 @@ test.describe('a11y', () => { }); test('autofocus from previous page is ignored', async ({ page, clicknav }) => { - page.addInitScript(` + await page.addInitScript(` window.active = null; window.addEventListener('focusin', () => window.active = document.activeElement); `); @@ -106,8 +107,13 @@ test.describe('a11y', () => { await page.goto('/accessibility/autofocus/a'); await clicknav('[href="/"]'); - expect(await page.evaluate(() => (window.active || {}).nodeName)).toBe('BODY'); - expect(await page.evaluate(() => (document.activeElement || {}).nodeName)).toBe('BODY'); + expect( + await page.evaluate( + // @ts-expect-error + () => window.active?.nodeName + ) + ).toBe('BODY'); + expect(await page.evaluate(() => document.activeElement?.nodeName)).toBe('BODY'); }); }); @@ -319,20 +325,18 @@ test.describe('Scrolling', () => { expect(await page.evaluate(() => scrollY)).toBe(0); }); - test('scroll is restored after hitting the back button', async ({ baseURL, clicknav, page }) => { + test('scroll is restored after hitting the back button', async ({ clicknav, page }) => { await page.goto('/anchor'); await page.locator('#scroll-anchor').click(); const originalScrollY = /** @type {number} */ (await page.evaluate(() => scrollY)); await clicknav('#routing-page'); await page.goBack(); - await page.waitForLoadState('networkidle'); - expect(page.url()).toBe(baseURL + '/anchor#last-anchor-2'); + + await expect(page).toHaveURL('/anchor#last-anchor-2'); expect(await page.evaluate(() => scrollY)).toEqual(originalScrollY); await page.goBack(); - await page.waitForLoadState('networkidle'); - - expect(page.url()).toBe(baseURL + '/anchor'); + await expect(page).toHaveURL('/anchor'); expect(await page.evaluate(() => scrollY)).toEqual(0); }); @@ -587,18 +591,15 @@ test.describe('Prefetching', () => { expect(requests.filter((req) => req.endsWith('.js')).length).toBeGreaterThan(0); } - expect(requests.includes(`${baseURL}/routing/preloading/preloaded.json`)).toBe(true); + expect(requests).toContain(`${baseURL}/routing/preloading/preloaded.json`); requests = []; await app.goto('/routing/preloading/preloaded'); expect(requests).toEqual([]); - try { - await app.preloadData('https://example.com'); - throw new Error('Error was not thrown'); - } catch (/** @type {any} */ e) { - expect(e.message).toMatch('Attempted to preload a URL that does not belong to this app'); - } + await expect(app.preloadData('https://example.com')).rejects.toThrowError( + 'Attempted to preload a URL that does not belong to this app' + ); }); test('chooses correct route when hash route is preloaded but regular route is clicked', async ({ @@ -693,8 +694,9 @@ test.describe('Routing', () => { await page.locator('[href="#hash-target"]').click(); await clicknav('[href="/routing/hashes/b"]'); + await expect(page.locator('h1')).toHaveText('b'); await page.goBack(); - expect(await page.textContent('h1')).toBe('a'); + await expect(page.locator('h1')).toHaveText('a'); }); test('replaces state if the data-sveltekit-replacestate router option is specified for the hash link', async ({ @@ -746,6 +748,7 @@ test.describe('Routing', () => { test('responds to