Skip to content

Commit c29b61e

Browse files
author
Rich Harris
authored
Announce page changes (#311)
* rename tests * announce page changes (#307) * try to reduce flakiness
1 parent 72da270 commit c29b61e

File tree

11 files changed

+80
-10
lines changed

11 files changed

+80
-10
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
Announce page changes

packages/kit/src/core/create_app.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ function generate_app(manifest_data) {
133133
return trim(`
134134
<!-- This file is generated by @sveltejs/kit — do not edit it! -->
135135
<script>
136-
import { setContext, afterUpdate } from 'svelte';
136+
import { setContext, afterUpdate, onMount } from 'svelte';
137137
import ErrorComponent from ${JSON.stringify(manifest_data.error.url)};
138138
139139
// error handling
@@ -153,6 +153,22 @@ function generate_app(manifest_data) {
153153
154154
$: stores.page.set(page);
155155
afterUpdate(stores.page.notify);
156+
157+
let mounted = false;
158+
let navigated = false;
159+
let title = null;
160+
161+
onMount(() => {
162+
const unsubscribe = stores.page.subscribe(() => {
163+
if (mounted) {
164+
navigated = true;
165+
title = document.title;
166+
}
167+
});
168+
169+
mounted = true;
170+
return unsubscribe;
171+
});
156172
</script>
157173
158174
<Layout {...(props_0 || {})}>
@@ -162,5 +178,25 @@ function generate_app(manifest_data) {
162178
${pyramid.replace(/\n/g, '\n\t\t\t\t')}
163179
{/if}
164180
</Layout>
181+
182+
{#if mounted}
183+
<div id="svelte-announcer" aria-live="assertive" aria-atomic="true">
184+
{#if navigated}
185+
Navigated to {title}
186+
{/if}
187+
</div>
188+
{/if}
189+
190+
<style>
191+
#svelte-announcer {
192+
clip: rect(0 0 0 0);
193+
clip-path: inset(50%);
194+
height: 1px;
195+
overflow: hidden;
196+
position: absolute;
197+
white-space: nowrap;
198+
width: 1px;
199+
}
200+
</style>
165201
`);
166202
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<nav><a href="/accessibility/a">a</a> <a href="/accessibility/b">b</a></nav>
2+
3+
<slot />

test/apps/basics/src/routes/focus/__tests__.js renamed to test/apps/basics/src/routes/accessibility/__tests__.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,39 @@ import * as assert from 'uvu/assert';
22

33
export default function (test) {
44
test('resets focus', async ({ visit, click, keyboard, evaluate, contains }) => {
5-
await visit('/focus/a');
5+
await visit('/accessibility/a');
66

7-
await click('[href="/focus/b"]');
7+
await click('[href="/accessibility/b"]');
88
assert.ok(await contains('b'));
99
assert.equal(await evaluate(() => document.activeElement.nodeName), 'BODY');
1010
await keyboard.press('Tab');
1111
assert.equal(await evaluate(() => document.activeElement.nodeName), 'A');
1212
assert.equal(await evaluate(() => document.activeElement.textContent), 'a');
1313

14-
await click('[href="/focus/a"]');
14+
await click('[href="/accessibility/a"]');
1515
assert.ok(await contains('a'));
1616
assert.equal(await evaluate(() => document.activeElement.nodeName), 'BODY');
1717
await keyboard.press('Tab');
1818
assert.equal(await evaluate(() => document.activeElement.nodeName), 'A');
1919
assert.equal(await evaluate(() => document.activeElement.textContent), 'a');
2020
});
21+
22+
test('announces client-side navigation', async ({ visit, click, contains, html, sleep, js }) => {
23+
await visit('/accessibility/a');
24+
25+
const has_live_region = await contains('aria-live');
26+
27+
if (js) {
28+
assert.ok(has_live_region);
29+
30+
// live region should exist, but be empty
31+
assert.equal(await html('[aria-live]'), '');
32+
33+
await click('[href="/accessibility/b"]');
34+
await sleep(50);
35+
assert.equal(await html('[aria-live]'), 'Navigated to b'); // TODO i18n
36+
} else {
37+
assert.ok(!has_live_region);
38+
}
39+
});
2140
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<svelte:head>
2+
<title>a</title>
3+
</svelte:head>
4+
5+
<p>a</p>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<svelte:head>
2+
<title>b</title>
3+
</svelte:head>
4+
5+
<p>b</p>

test/apps/basics/src/routes/focus/$layout.svelte

Lines changed: 0 additions & 3 deletions
This file was deleted.

test/apps/basics/src/routes/focus/a.svelte

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/apps/basics/src/routes/focus/b.svelte

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/apps/basics/src/routes/routing/__tests__.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export default function (test) {
102102
capture_requests,
103103
click,
104104
wait_for_function,
105+
sleep,
105106
js
106107
}) => {
107108
if (js) {
@@ -114,7 +115,7 @@ export default function (test) {
114115

115116
// weird flakiness — without this, some requests are
116117
// reported after prefetch_routes has finished
117-
await new Promise((f) => setTimeout(f, 200));
118+
await sleep(200);
118119

119120
const requests = await capture_requests(async () => {
120121
await click('a[href="/routing/a"]');

test/runner.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ async function setup({ port }) {
7777
set_extra_http_headers: (headers) => page.setExtraHTTPHeaders(headers),
7878
pathname: () => page.url().replace(base, ''),
7979
keyboard: page.keyboard,
80+
sleep: (ms) => new Promise((f) => setTimeout(f, ms)),
8081
$: (selector) => page.$(selector)
8182
};
8283
}

0 commit comments

Comments
 (0)