Skip to content

Commit 7ed5def

Browse files
mstenshochromium-wpt-export-bot
authored andcommitted
[RouteMatching] Untangle NavigationState from RouteMap.
Make :nav-source shippable, by associating NavigationState with Document rather than RouteMap, and by introducing a runtime feature NavigationState. The existing RouteMatching feature now depends on that feature. On its own, NavigationState only provides support for :nav-source. Upstream existing :nav-source test. Bug: 436805487 Change-Id: Ifde73ca221c1500cddc416793c2bbf1fed4fc08e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8153282 Commit-Queue: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Morten Stenshorne <mstensho@chromium.org> Reviewed-by: Noam Rosenthal <nrosenthal@google.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1669298}
1 parent 6ef32b0 commit 7ed5def

3 files changed

Lines changed: 129 additions & 0 deletions

File tree

css/css-navigation/META.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
spec: https://drafts.csswg.org/css-navigation-1/
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<!DOCTYPE html>
2+
<title>:nav-source</title>
3+
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
4+
<link rel="help" href="https://drafts.csswg.org/css-navigation-1/#nav-source-pseudo-class">
5+
<style>
6+
:nav-source {
7+
--trigger: matched;
8+
}
9+
</style>
10+
<a id="elm1" href="/target/">elm</a>
11+
<a id="elm2" href="/target/">elm</a>
12+
<a id="elm3" href="/different/">elm</a>
13+
<form id="form1" action="/target/"><input type="submit" id="btn1"></form>
14+
<form id="form2" action="/target/"></form>
15+
<form id="form3" action="/target/"><input type="submit" id="btn3"></form>
16+
<form id="form4" action="/target/"></form>
17+
<script src="/resources/testharness.js"></script>
18+
<script src="/resources/testharnessreport.js"></script>
19+
<script src="/resources/testdriver.js"></script>
20+
<script src="/resources/testdriver-actions.js"></script>
21+
<script src="/resources/testdriver-vendor.js"></script>
22+
<script src="resources/test-navigation.js"></script>
23+
<script>
24+
async function clickElm(elm) {
25+
let rect = elm.getBoundingClientRect();
26+
await new test_driver.Actions().pointerMove(rect.left + 2, rect.top + 2).pointerDown().pointerUp().send();
27+
}
28+
29+
promise_test(async (t) => {
30+
await new Promise(r => window.onload = () => t.step_timeout(r, 0));
31+
32+
const match_params = [
33+
[elm1, "--trigger"],
34+
[elm2, "--trigger"],
35+
[elm3, "--trigger"],
36+
[btn1, "--trigger"],
37+
[form2, "--trigger"],
38+
[btn3, "--trigger"],
39+
[form4, "--trigger"],
40+
];
41+
42+
await test_navigation(t, "nav1", ()=> { clickElm(elm1); }, [1,0,0,0,0,0,0], [1,0,0,0,0,0,0], match_params);
43+
await test_navigation(t, "nav2", ()=> { navigation.back(); }, [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], match_params);
44+
await test_navigation(t, "nav3", ()=> { navigation.forward(); }, [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], match_params);
45+
await test_navigation(t, "nav4", ()=> { clickElm(elm2); }, [0,1,0,0,0,0,0], [0,1,0,0,0,0,0], match_params);
46+
await test_navigation(t, "nav5", ()=> { clickElm(btn1); }, [0,0,0,1,0,0,0], [0,0,0,1,0,0,0], match_params);
47+
await test_navigation(t, "nav6", ()=> { form2.submit(); }, [0,0,0,0,1,0,0], [0,0,0,0,1,0,0], match_params);
48+
await test_navigation(t, "nav7", ()=> { form3.requestSubmit(btn3); }, [0,0,0,0,0,1,0], [0,0,0,0,0,1,0], match_params);
49+
await test_navigation(t, "nav8", ()=> { form4.requestSubmit(); }, [0,0,0,0,0,0,1], [0,0,0,0,0,0,1], match_params);
50+
}, ":nav-source");
51+
</script>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
function matches(elm, property) {
2+
return getComputedStyle(elm).getPropertyValue(property) == 'matched' ? 1 : 0;
3+
}
4+
5+
function get_match_result(match_params) {
6+
let result = new Array();
7+
for (param of match_params) {
8+
result.push(matches(param[0], param[1]));
9+
}
10+
return result;
11+
}
12+
13+
function assert_match_result(result, expectation, stage, match_params) {
14+
assert_equals(result.length, expectation.length, 'Array length mismatch');
15+
for (let idx = 0; idx < result.length; idx++) {
16+
assert_equals(result[idx], expectation[idx],
17+
`${match_params[idx][0].id} ${
18+
match_params[idx][1]} mismatch, unexpectedly ${
19+
result[idx]} at stage ${stage}`);
20+
}
21+
}
22+
23+
async function test_navigation(t, test_id, operation, onnavigate_expectations,
24+
committed_expectations, match_params) {
25+
let nav = Promise.withResolvers();
26+
let precommit = Promise.withResolvers();
27+
let handler = Promise.withResolvers();
28+
navigation.onnavigate =
29+
(event) => {
30+
nav.resolve();
31+
event.intercept({
32+
async precommitHandler() {
33+
precommit.resolve();
34+
await new Promise(r => t.step_timeout(r, 0));
35+
},
36+
async handler() {
37+
handler.resolve();
38+
await new Promise(resolve => requestAnimationFrame(resolve));
39+
}
40+
})
41+
}
42+
43+
// Prevent the test from failing asserts at certain stages, since that would
44+
// interfere with the testharness framework, so that the test would hang
45+
// instead of failing. Store the result, and check them later, at a safe
46+
// stage.
47+
let onnavigate_result,
48+
precommit_result;
49+
50+
const empty_result = new Array(match_params.length);
51+
empty_result.fill(0);
52+
53+
assert_match_result(get_match_result(match_params), empty_result,
54+
`${test_id} before`, match_params);
55+
operation();
56+
await nav.promise;
57+
onnavigate_result = get_match_result(match_params);
58+
await precommit.promise;
59+
precommit_result = get_match_result(match_params);
60+
await navigation.transition.committed;
61+
assert_match_result(onnavigate_result, onnavigate_expectations,
62+
`${test_id} onnavigate`, match_params);
63+
assert_match_result(precommit_result, onnavigate_result,
64+
`${test_id} precommit`, match_params);
65+
const result = get_match_result(match_params);
66+
assert_match_result(result, committed_expectations, `${test_id} committed`,
67+
match_params);
68+
const previous_result = result;
69+
await handler.promise;
70+
assert_match_result(get_match_result(match_params), previous_result,
71+
`${test_id} handler`, match_params);
72+
await new Promise(r => navigation.onnavigatesuccess = () =>
73+
t.step_timeout(r, 0));
74+
75+
assert_match_result(get_match_result(match_params), empty_result,
76+
`${test_id} after`, match_params);
77+
}

0 commit comments

Comments
 (0)