Update web-platform-tests to revision b'b728032f59a396243864b0f8584e7211e3632005'

This commit is contained in:
WPT Sync Bot 2022-11-10 01:22:36 +00:00
parent ace9b32b1c
commit df68c4e5d1
15632 changed files with 514865 additions and 155000 deletions

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>toggle-group is not animatable</title>
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-group-property">
<meta name="assert" content="toggle-group is not animatable">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/interpolation-testcommon.js"></script>
<body>
<script>
test_not_animatable({
property: 'toggle-group',
from: 'atoggle',
to: 'yourtoggle',
underlying: 'mytoggle',
});
</script>
</body>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>toggle-root is not animatable</title>
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-root-property">
<meta name="assert" content="toggle-root is not animatable">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/interpolation-testcommon.js"></script>
<body>
<script>
test_not_animatable({
property: 'toggle-root',
from: 'none',
to: 'yourtoggle 3 at 1',
underlying: 'mytoggle 2',
});
</script>
</body>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>toggle-trigger is not animatable</title>
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<meta name="assert" content="toggle-trigger is not animatable">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/interpolation-testcommon.js"></script>
<body>
<script>
test_not_animatable({
property: 'toggle-trigger',
from: 'atoggle set 4',
to: 'yourtoggle set 3',
underlying: 'mytoggle set 2',
});
</script>
</body>

View file

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<meta charset=UTF-8>
<title>css-toggles IDL tests</title>
<link rel="help" href="https://tabatkins.github.io/css-toggle/#dom">
<link rel="help" href="https://github.com/tabatkins/css-toggle/issues/29">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/WebIDLParser.js></script>
<script src=/resources/idlharness.js></script>
<script src="support/toggle-helpers.js"></script>
<div id="toggles" style="toggle-root: mytoggle 3 at 1"></div>
<script type="module">
'use strict';
await wait_for_toggle_creation(document.getElementById("toggles"));
idl_test(
['css-toggle.tentative'],
['dom'],
idl_array => {
idl_array.add_objects({
CSSToggleMap: ['document.getElementById("toggles").toggles'],
CSSToggle: [
'document.getElementById("toggles").toggles.get("mytoggle")',
'new CSSToggle()',
'new CSSToggle({ value: 3, states: 7, group: true, scope: "narrow", cycle: "cycle-on"})',
'new CSSToggle({ value: "four", states: ["one", "two", "four", "eight"], group: false, scope: "wide", cycle: "sticky"})',
],
});
}
);
</script>

View file

@ -0,0 +1,107 @@
function test_toggle_root_computed_values(property) {
test_computed_value(property, 'none');
test_computed_value(property, 'sticky sticky');
test_computed_value(property, 'group group');
test_computed_value(property, 'self self');
test_computed_value(property, 'mytoggle');
test_computed_value(property, 'mytoggle, yourtoggle');
test_computed_value(property, 'mytoggle, mytoggle');
test_computed_value(property, 'mytoggle 3 at 0 sticky self, yourtoggle 1 group self', 'mytoggle 3 sticky self, yourtoggle group self');
test_computed_value(property, 'mytoggle 3 at 1 sticky self, yourtoggle 2 group self');
test_computed_value(property, 'mytoggle 1 at 0', 'mytoggle');
test_computed_value(property, 'mytoggle 1 at +0', 'mytoggle');
test_computed_value(property, 'mytoggle +1 at 0', 'mytoggle');
test_computed_value(property, 'mytoggle 1 at -0', 'mytoggle');
test_computed_value(property, 'mytoggle +1 at 2', 'mytoggle 1 at 2');
test_computed_value(property, 'mytoggle 1 at calc(-3)', 'mytoggle');
test_computed_value(property, 'mytoggle calc(-3) at 0', 'mytoggle');
test_computed_value(property, 'mytoggle 7 at calc(-3)', 'mytoggle 7');
test_computed_value(property, 'mytoggle calc(-3) at 7', 'mytoggle 1 at 7');
test_computed_value(property, 'mytoggle calc(9) at calc(6)', 'mytoggle 9 at 6');
test_computed_value(property, 'mytoggle calc(9.6) at calc(6.4)', 'mytoggle 10 at 6');
test_computed_value(property, 'mytoggle calc(-9.5) at calc(6.5)', 'mytoggle 1 at 7');
test_computed_value(property, 'mytoggle group sticky self, yourtoggle self sticky', 'mytoggle sticky group self, yourtoggle sticky self');
test_computed_value(property, 'mytoggle group 2 at 1', 'mytoggle 2 at 1 group');
test_computed_value(property, 'mytoggle [one two]');
test_computed_value(property, 'mytoggle [one two three]');
test_computed_value(property, 'mytoggle [one two three] at 0', 'mytoggle [one two three]');
test_computed_value(property, 'mytoggle [ one two three ] at 0', 'mytoggle [one two three]');
test_computed_value(property, 'mytoggle[one two three]at 0', 'mytoggle [one two three]');
test_computed_value(property, 'mytoggle [one two three] at 1');
test_computed_value(property, 'mytoggle [ one two three ] at 1', 'mytoggle [one two three] at 1');
test_computed_value(property, 'mytoggle[one two three]at 1', 'mytoggle [one two three] at 1');
test_computed_value(property, 'mytoggle [ one two three ] at two', 'mytoggle [one two three] at two');
test_computed_value(property, 'mytoggle 3 at two');
}
function test_toggle_root_valid_values(property) {
test_valid_value(property, 'none');
test_valid_value(property, 'sticky sticky');
test_valid_value(property, 'group group');
test_valid_value(property, 'self self');
test_valid_value(property, 'mytoggle');
test_valid_value(property, 'mytoggle, yourtoggle');
test_valid_value(property, 'mytoggle, mytoggle');
test_valid_value(property, 'mytoggle 3 at 0 sticky self, yourtoggle 1 group self');
test_valid_value(property, 'mytoggle 1 at 0');
test_valid_value(property, 'mytoggle 1 at +0', 'mytoggle 1 at 0');
test_valid_value(property, 'mytoggle +1 at 0', 'mytoggle 1 at 0');
test_valid_value(property, 'mytoggle 1 at -0', 'mytoggle 1 at 0');
test_valid_value(property, 'mytoggle 1 at calc(-3)');
test_valid_value(property, 'mytoggle calc(-3) at 0');
test_valid_value(property, 'mytoggle 7 at calc(-3)');
test_valid_value(property, 'mytoggle calc(-3) at 7');
test_valid_value(property, 'mytoggle calc(9) at calc(6)');
test_valid_value(property, 'mytoggle calc(9.6) at calc(6.4)');
test_valid_value(property, 'mytoggle calc(-9.5) at calc(6.5)');
test_valid_value(property, 'mytoggle group sticky self, yourtoggle self sticky', 'mytoggle sticky group self, yourtoggle sticky self');
test_valid_value(property, 'mytoggle group 2 at 1', 'mytoggle 2 at 1 group');
test_valid_value(property, 'mytoggle [one two]');
test_valid_value(property, 'mytoggle [one two three]');
test_valid_value(property, 'mytoggle [one two three] at 0');
test_valid_value(property, 'mytoggle [ one two three ] at 0', 'mytoggle [one two three] at 0');
test_valid_value(property, 'mytoggle[one two three]at 0', 'mytoggle [one two three] at 0');
test_valid_value(property, 'mytoggle [ one two three ] at two', 'mytoggle [one two three] at two');
test_valid_value(property, 'mytoggle 3 at two');
}
function test_toggle_root_invalid_values(property) {
test_invalid_value(property, 'none 1');
test_invalid_value(property, 'none sticky');
test_invalid_value(property, 'none cycle');
test_invalid_value(property, 'none cycle-on');
test_invalid_value(property, 'none group');
test_invalid_value(property, 'none self');
test_invalid_value(property, 'None self');
test_invalid_value(property, 'NONE self');
test_invalid_value(property, 'mytoggle sticky sticky');
test_invalid_value(property, 'mytoggle group group');
test_invalid_value(property, 'mytoggle self self');
test_invalid_value(property, 'none sticky sticky');
test_invalid_value(property, 'none group group');
test_invalid_value(property, 'none self self');
test_invalid_value(property, 'none, mytoggle');
test_invalid_value(property, 'mytoggle, none');
test_invalid_value(property, 'mytoggle 1 at');
test_invalid_value(property, 'mytoggle []');
test_invalid_value(property, 'mytoggle [one]');
test_invalid_value(property, 'mytoggle [one two] at');
test_invalid_value(property, 'mytoggle [one two two three]');
test_invalid_value(property, 'mytoggle [one two one three]');
test_invalid_value(property, 'mytoggle 0 sticky self');
test_invalid_value(property, 'mytoggle 0 at 0 sticky self');
test_invalid_value(property, 'mytoggle -1 at 1 sticky self');
test_invalid_value(property, 'mytoggle 1 at -1 sticky self');
test_invalid_value(property, 'mytoggle -1 at -1 sticky self');
test_invalid_value(property, 'mytoggle -1 at 0');
test_invalid_value(property, 'mytoggle 0 at 0');
test_invalid_value(property, 'mytoggle -0 at 0');
test_invalid_value(property, 'mytoggle +0 at 0');
test_invalid_value(property, 'mytoggle sticky 3 at 1 group self sticky');
test_invalid_value(property, 'mytoggle sticky 3 at 1 group self group');
test_invalid_value(property, 'mytoggle sticky 3 at 1 group self self');
test_invalid_value(property, 'mytoggle sticky 3 at 1 group self 1');
test_invalid_value(property, 'mytoggle sticky group at 1');
test_invalid_value(property, 'mytoggle sticky group at 1 1');
}

View file

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: getComputedStyle() for toggle property</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<script src="support/toggle-root-values.js"></script>
<body>
<div id="target"></div>
<script>
test_toggle_root_computed_values('toggle');
</script>

View file

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: getComputedStyle() for toggle-group property</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-group-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<body>
<div id="target"></div>
<script>
test_computed_value('toggle-group', 'none');
test_computed_value('toggle-group', 'self self');
test_computed_value('toggle-group', 'mytoggle');
test_computed_value('toggle-group', 'mytoggle, yourtoggle');
test_computed_value('toggle-group', 'mytoggle, mytoggle');
test_computed_value('toggle-group', 'mytoggle self, yourtoggle');
test_computed_value('toggle-group', 'mytoggle self , yourtoggle self', 'mytoggle self, yourtoggle self');
test_computed_value('toggle-group', 'mytoggle,yourtoggle self', 'mytoggle, yourtoggle self');
</script>

View file

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-group with invalid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-group-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<body>
<script>
test_invalid_value('toggle-group', 'none, none');
test_invalid_value('toggle-group', 'none self');
test_invalid_value('toggle-group', 'None self');
test_invalid_value('toggle-group', 'NONE self');
test_invalid_value('toggle-group', 'mytoggle self self');
test_invalid_value('toggle-group', 'none, mytoggle');
test_invalid_value('toggle-group', 'mytoggle, none');
test_invalid_value('toggle-group', 'mytoggle 1 self');
test_invalid_value('toggle-group', 'mytoggle self 1');
test_invalid_value('toggle-group', 'mytoggle sticky self');
test_invalid_value('toggle-group', 'mytoggle self sticky');
</script>

View file

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-group with valid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-group-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<body>
<script>
test_valid_value('toggle-group', 'none');
test_valid_value('toggle-group', 'self self');
test_valid_value('toggle-group', 'mytoggle');
test_valid_value('toggle-group', 'mytoggle, yourtoggle');
test_valid_value('toggle-group', 'mytoggle, mytoggle');
test_valid_value('toggle-group', 'mytoggle self, yourtoggle');
test_valid_value('toggle-group', 'mytoggle self , yourtoggle self', 'mytoggle self, yourtoggle self');
test_valid_value('toggle-group', 'mytoggle,yourtoggle self', 'mytoggle, yourtoggle self');
</script>

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle with invalid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script src="support/toggle-root-values.js"></script>
<body>
<script>
test_toggle_root_invalid_values('toggle');
</script>

View file

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: getComputedStyle() for toggle-root property</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-root-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<script src="support/toggle-root-values.js"></script>
<body>
<div id="target"></div>
<script>
test_toggle_root_computed_values('toggle-root');
</script>

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-root with invalid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-root-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script src="support/toggle-root-values.js"></script>
<body>
<script>
test_toggle_root_invalid_values('toggle-root');
</script>

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-root with valid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-root-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script src="support/toggle-root-values.js"></script>
<body>
<script>
test_toggle_root_valid_values('toggle-root');
</script>

View file

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: getComputedStyle() for toggle-trigger property</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<body>
<div id="target"></div>
<script>
test_computed_value('toggle-trigger', 'none');
test_computed_value('toggle-trigger', 'self set 1');
test_computed_value('toggle-trigger', 'sticky set 1');
test_computed_value('toggle-trigger', 'group set 1');
test_computed_value('toggle-trigger', 'mytoggle');
test_computed_value('toggle-trigger', 'mytoggle set 0');
test_computed_value('toggle-trigger', 'mytoggle set +0', 'mytoggle set 0');
test_computed_value('toggle-trigger', 'mytoggle set -0', 'mytoggle set 0');
test_computed_value('toggle-trigger', 'mytoggle set +5', 'mytoggle set 5');
test_computed_value('toggle-trigger', 'mytoggle, yourtoggle');
test_computed_value('toggle-trigger', 'mytoggle, mytoggle');
test_computed_value('toggle-trigger', 'mytoggle set 1, yourtoggle');
test_computed_value('toggle-trigger', 'mytoggle set 1 , yourtoggle set 1', 'mytoggle set 1, yourtoggle set 1');
test_computed_value('toggle-trigger', 'mytoggle,yourtoggle set 1', 'mytoggle, yourtoggle set 1');
test_computed_value('toggle-trigger', 'mytoggle set calc(-3)', 'mytoggle set 0');
test_computed_value('toggle-trigger', 'mytoggle set calc(6)', 'mytoggle set 6');
test_computed_value('toggle-trigger', 'mytoggle set calc(6.4)', 'mytoggle set 6');
test_computed_value('toggle-trigger', 'mytoggle set calc(6.5)', 'mytoggle set 7');
test_computed_value('toggle-trigger', 'mytoggle set calc(6.6)', 'mytoggle set 7');
test_computed_value('toggle-trigger', 'mytoggle set two');
test_computed_value('toggle-trigger', 'mytoggle next 1', 'mytoggle');
test_computed_value('toggle-trigger', 'mytoggle next 2');
test_computed_value('toggle-trigger', 'mytoggle prev 1', 'mytoggle prev');
test_computed_value('toggle-trigger', 'mytoggle prev 2');
test_computed_value('toggle-trigger', 'mytoggle next calc(-3)', 'mytoggle');
test_computed_value('toggle-trigger', 'mytoggle prev calc(-3)', 'mytoggle prev');
test_computed_value('toggle-trigger', 'mytoggle next calc(6.4)', 'mytoggle next 6');
test_computed_value('toggle-trigger', 'mytoggle next calc(6.5)', 'mytoggle next 7');
test_computed_value('toggle-trigger', 'mytoggle prev calc(6.4)', 'mytoggle prev 6');
test_computed_value('toggle-trigger', 'mytoggle prev calc(6.5)', 'mytoggle prev 7');
</script>

View file

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-trigger with invalid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<body>
<script>
test_invalid_value('toggle-trigger', 'none, none');
test_invalid_value('toggle-trigger', 'none set 1');
test_invalid_value('toggle-trigger', 'None set 1');
test_invalid_value('toggle-trigger', 'NONE set 1');
test_invalid_value('toggle-trigger', 'mytoggle set 1 1');
test_invalid_value('toggle-trigger', 'mytoggle set -1');
test_invalid_value('toggle-trigger', 'none, mytoggle');
test_invalid_value('toggle-trigger', 'mytoggle, none');
test_invalid_value('toggle-trigger', 'mytoggle self 1');
test_invalid_value('toggle-trigger', 'mytoggle 1 self');
test_invalid_value('toggle-trigger', 'mytoggle sticky 1');
test_invalid_value('toggle-trigger', 'mytoggle 1 sticky');
test_invalid_value('toggle-trigger', 'mytoggle self set 1');
test_invalid_value('toggle-trigger', 'mytoggle set 1 self');
test_invalid_value('toggle-trigger', 'mytoggle sticky set 1');
test_invalid_value('toggle-trigger', 'mytoggle set 1 sticky');
</script>

View file

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-trigger with valid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<body>
<script>
test_valid_value('toggle-trigger', 'none');
test_valid_value('toggle-trigger', 'self set 1');
test_valid_value('toggle-trigger', 'sticky set 1');
test_valid_value('toggle-trigger', 'group set 1');
test_valid_value('toggle-trigger', 'mytoggle');
test_valid_value('toggle-trigger', 'mytoggle set 0');
test_valid_value('toggle-trigger', 'mytoggle set +0', 'mytoggle set 0');
test_valid_value('toggle-trigger', 'mytoggle set -0', 'mytoggle set 0');
test_valid_value('toggle-trigger', 'mytoggle set +5', 'mytoggle set 5');
test_valid_value('toggle-trigger', 'mytoggle, yourtoggle');
test_valid_value('toggle-trigger', 'mytoggle, mytoggle');
test_valid_value('toggle-trigger', 'mytoggle set 1, yourtoggle');
test_valid_value('toggle-trigger', 'mytoggle set 1 , yourtoggle set 1', 'mytoggle set 1, yourtoggle set 1');
test_valid_value('toggle-trigger', 'mytoggle,yourtoggle set 1', 'mytoggle, yourtoggle set 1');
test_valid_value('toggle-trigger', 'mytoggle set calc(-3)');
test_valid_value('toggle-trigger', 'mytoggle set calc(6)');
test_valid_value('toggle-trigger', 'mytoggle set calc(6.4)');
test_valid_value('toggle-trigger', 'mytoggle set calc(6.5)');
test_valid_value('toggle-trigger', 'mytoggle set calc(6.6)');
test_valid_value('toggle-trigger', 'mytoggle set two');
test_valid_value('toggle-trigger', 'mytoggle next 1');
test_valid_value('toggle-trigger', 'mytoggle next 2');
test_valid_value('toggle-trigger', 'mytoggle prev 1');
test_valid_value('toggle-trigger', 'mytoggle prev 2');
test_valid_value('toggle-trigger', 'mytoggle next calc(-3)');
test_valid_value('toggle-trigger', 'mytoggle prev calc(-3)');
test_valid_value('toggle-trigger', 'mytoggle next calc(6.4)');
test_valid_value('toggle-trigger', 'mytoggle next calc(6.5)');
test_valid_value('toggle-trigger', 'mytoggle prev calc(6.4)');
test_valid_value('toggle-trigger', 'mytoggle prev calc(6.5)');
</script>

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle with valid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script src="support/toggle-root-values.js"></script>
<body>
<script>
test_toggle_root_valid_values('toggle');
</script>

View file

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: getComputedStyle() for toggle-visibility property</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
<body>
<div id="target"></div>
<script>
test_computed_value('toggle-visibility', 'normal');
test_computed_value('toggle-visibility', 'toggle t');
test_computed_value('toggle-visibility', 'toggle toggle');
</script>

View file

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-visibility with invalid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<body>
<script>
test_invalid_value('toggle-visibility', 'none');
test_invalid_value('toggle-visibility', 'toggle');
test_invalid_value('toggle-visibility', 't');
test_invalid_value('toggle-visibility', 'normal, toggle t');
test_invalid_value('toggle-visibility', 'toggle t, normal');
test_invalid_value('toggle-visibility', 'toggle a, toggle t');
</script>

View file

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: parsing toggle-visibility with valid values</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<body>
<script>
test_valid_value('toggle-visibility', 'normal');
test_valid_value('toggle-visibility', 'toggle t');
test_valid_value('toggle-visibility', 'toggle toggle');
</script>

View file

@ -0,0 +1,16 @@
async function wait_for_toggle_creation(element) {
// TODO(crbug.com/1250716): The spec is vague about when toggles need to be
// created, and whether :toggle() pseudo-classes will update within the same
// update. See https://github.com/tabatkins/css-toggle/issues/27 . For
// now, we call elementFromPoint (which in Chromium flushes to PrePaint
// clean), which isn't a long term solution!
document.elementFromPoint(10, 10);
}
async function set_up_single_toggle_in(container, toggle_style) {
let div = document.createElement("div");
div.style.toggle = toggle_style;
container.replaceChildren(div);
await wait_for_toggle_creation(div);
return div;
}

View file

@ -0,0 +1,336 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: activation of toggles</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#fire-a-toggle-activation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<style id="style"></style>
<body>
<div id="container"></div>
<script>
let container = document.getElementById("container");
function test_trigger_on_group(toggle_specifier, other_specifier, action, toggle_expected, group_expected)
{
promise_test(async function() {
let group = document.createElement("div");
group.style.toggleGroup = "test-group";
let toggle = document.createElement("div");
toggle.style.toggle = `test-group ${toggle_specifier} group`;
toggle.style.toggleTrigger = `test-group ${action}`;
group.appendChild(toggle);
let other = document.createElement("div");
other.style.toggle = `test-group ${other_specifier} group`;
group.appendChild(other);
let style = document.getElementById("style");
style.textContent = `
:toggle(test-group ${toggle_expected}) { --v:${toggle_expected}; }
:toggle(test-group ${group_expected}) { --v:${group_expected}; }
`;
container.replaceChildren(group);
await wait_for_toggle_creation(toggle);
toggle.click();
assert_true(toggle.matches(`:toggle(test-group ${toggle_expected}`), "value of triggered toggle");
assert_equals(getComputedStyle(toggle).getPropertyValue("--v"), toggle_expected, "style on triggered toggle");
assert_true(other.matches(`:toggle(test-group ${group_expected}`), "value of other toggle in group");
assert_equals(getComputedStyle(other).getPropertyValue("--v"), group_expected, "style on other toggle in group");
}, `group behavior for toggle "${toggle_specifier}" and action "${action}" with other element in group "${other_specifier}"`);
}
test_trigger_on_group("", "", "next", "1", "0");
test_trigger_on_group("1 at 0", "1 at 0", "next", "1", "0");
test_trigger_on_group("", "1 at 1", "next", "1", "0");
test_trigger_on_group("1 at 1", "1 at 1", "next", "0", "1");
test_trigger_on_group("1 at 1 cycle", "1 at 1", "next", "0", "1");
test_trigger_on_group("1 at 1 cycle-on", "1 at 1", "next", "1", "0");
test_trigger_on_group("1 at 1 sticky", "1 at 1", "next", "1", "0");
test_trigger_on_group("1 at 1", "1 at 1", "set 3", "3", "0");
test_trigger_on_group("1 at 1", "1 at 1", "set 0", "0", "1");
test_trigger_on_group("1 at 7", "1 at 5", "set 9", "9", "0");
test_trigger_on_group("1 at 7", "1 at 5", "set 0", "0", "5");
test_trigger_on_group("", "1 at 1 cycle", "next", "1", "0");
test_trigger_on_group("", "1 at 1 cycle-on", "next", "1", "0");
test_trigger_on_group("", "1 at 1 sticky", "next", "1", "0");
test_trigger_on_group("1 at 0", "1 at 1", "prev", "1", "0");
test_trigger_on_group("1 at 0", "1 at 0", "prev", "1", "0");
test_trigger_on_group("1 at 1", "1 at 1", "prev", "0", "1");
test_trigger_on_group("1 at 1 cycle", "1 at 1", "prev", "0", "1");
test_trigger_on_group("1 at 1 cycle-on", "1 at 1", "prev", "1", "0");
test_trigger_on_group("1 at 1 sticky", "1 at 1", "prev", "0", "1");
test_trigger_on_group("", "1 at 1", "set 0", "0", "1");
test_trigger_on_group("", "1 at 1", "set 1", "1", "0");
test_trigger_on_group("", "1 at 1", "set 7", "7", "0");
test_trigger_on_group("", "1 at 1", "set named-state", "named-state", "0");
test_trigger_on_group("[a b c] at a", "1 at 1", "next", "b", "0");
test_trigger_on_group("[a b c] at c", "1 at 1", "next", "a", "1");
test_trigger_on_group("[a b c] at a", "1 at 1", "prev", "c", "0");
test_trigger_on_group("[a b c] at b", "1 at 1", "prev", "a", "1");
test_trigger_on_group("[a b c] at b", "1 at 1", "set 2", "c", "0");
test_trigger_on_group("[a b c] at b", "1 at 1", "set c", "c", "0");
test_trigger_on_group("[a b c] at b", "1 at 1", "set 0", "0", "1");
test_trigger_on_group("[a b c] at b", "1 at 1", "set a", "0", "1");
test_trigger_on_group("[a b c] at b", "1 at 1", "set new-state", "new-state", "0");
test_trigger_on_group("", "[a b c] at b", "next", "1", "a");
test_trigger_on_group("", "[a b c] at b", "prev", "1", "a");
test_trigger_on_group("", "[a b c] at b", "set 1", "1", "a");
test_trigger_on_group("", "[a b c] at b", "set 0", "0", "b");
let finding_group_tests = [
// Markup to create the test assertions:
// class=assert-in: assert that this element's in-scope toggle is in the
// test-group group and was not the activated toggle
// class=assert-out: assert that this element's in-scope toggle is not in
// the test-group group and was not the activated toggle
// class=assert-activated: assert that this element's in-scope toggle was
// the activated toggle
//
// Helper markup to create more markup:
// class=establish: establish the group with the toggle-group property
// class=establish-self: same, but with the self keyword (narrow scope)
// class=root: create a test-group toggle with the toggle-root property
// class=root-nogroup: same, but without the 'group' keyword
// class=activate: toggle-trigger to activate test-group toggle
//
// class=activate (above) is *also* a helper to run the test; it will be
// activated. There must only be one element with class=activate.
`
<div class="establish"></div>
<div class="root assert-in"></div>
<div class="root-nogroup assert-out"></div>
<div class="root activate assert-activated"></div>
`,
`
<div class="establish"></div>
<div class="root assert-out"></div>
<div class="establish"></div>
<div class="root assert-in"></div>
<div class="root activate assert-activated"></div>
`,
`
<div class="establish"></div>
<div class="root activate assert-activated"></div>
<div class="root assert-in"></div>
<div class="establish"></div>
<div class="root assert-out"></div>
`,
`
<div class="establish"></div>
<div class="root assert-in"></div>
<div class="establish-self">
<div class="root assert-out"></div>
</div>
<div class="root assert-in"></div>
<div class="root activate assert-activated"></div>
`,
`
<div class="establish"></div>
<div class="root assert-out"></div>
<div class="establish">
<div class="root assert-in"></div>
</div>
<div class="root assert-in"></div>
<div class="root activate assert-activated"></div>
`,
`
<div class="establish"></div>
<div class="root activate assert-activated"></div>
<div class="root assert-in"></div>
<div class="establish">
<div class="root assert-out"></div>
</div>
<div class="root assert-out"></div>
`,
`
<div class="establish"></div>
<div class="root assert-in"></div>
<div class="establish-self"></div>
<div class="root assert-activated"></div>
<div class="activate"></div>
`,
`
<div class="root activate assert-activated"></div>
<div class="root assert-in"></div>
`,
`
<div class="root assert-out"></div>
<div class="establish-self">
<div class="root activate assert-activated"></div>
<div class="root assert-in"></div>
</div>
<div class="root assert-out"></div>
`,
`
<div class="root assert-out"></div>
<div style="toggle-group: test-group self, extra-group">
<div class="root activate assert-activated"></div>
<div class="root assert-in"></div>
</div>
<div class="root assert-out"></div>
`,
`
<div class="root assert-out"></div>
<div style="toggle-group: extra-group, test-group self">
<div class="root activate assert-activated"></div>
<div class="root assert-in"></div>
</div>
<div class="root assert-out"></div>
`,
`
<div class="root activate assert-activated">
<div class="establish">
<div class="root assert-out"></div>
</div>
<div class="root assert-out"></div>
</div>
`,
`
<div class="root activate assert-activated">
<div class="establish-self">
<div class="root assert-out"></div>
</div>
<div class="root assert-in"></div>
</div>
`,
`
<div class="root activate assert-activated">
<div class="root assert-in"></div>
<div>
<div class="root assert-in"></div>
<div class="establish">
<div class="root assert-out"></div>
</div>
<div class="root assert-out"></div>
</div>
<div class="root assert-in"></div>
</div>
`,
];
for (let t of finding_group_tests) {
promise_test(async function() {
document.getElementById("style").textContent = `
:toggle(test-group 0) { --v:0; }
:toggle(test-group 1) { --v:1; }
:toggle(test-group 2) { --v:2; }
`;
container.innerHTML = t;
for (let e of container.querySelectorAll('.establish')) {
e.style.toggleGroup = "test-group";
}
for (let e of container.querySelectorAll('.establish-self')) {
e.style.toggleGroup = "test-group self";
}
for (let e of container.querySelectorAll('.root')) {
e.style.toggleRoot = "test-group 1 at 1 cycle-on group";
}
for (let e of container.querySelectorAll('.root-nogroup')) {
e.style.toggleRoot = "test-group 1 at 1 cycle-on";
}
let activate = container.querySelector('.activate');
activate.style.toggleTrigger = "test-group set 2";
for (let e of container.querySelectorAll('.root, .root-nogroup')) {
await wait_for_toggle_creation(e);
}
activate.click();
for (let e of container.querySelectorAll('.assert-in')) {
assert_true(e.matches(":toggle(test-group 0)"), "element in group");
assert_equals(getComputedStyle(e).getPropertyValue("--v"), "0",
"style on element in group");
}
for (let e of container.querySelectorAll('.assert-out')) {
assert_true(e.matches(":toggle(test-group 1)"), "element not in group");
assert_equals(getComputedStyle(e).getPropertyValue("--v"), "1",
"style on element not in group");
}
for (let e of container.querySelectorAll('.assert-activated')) {
assert_true(e.matches(":toggle(test-group 2)"), "element was activated");
assert_equals(getComputedStyle(e).getPropertyValue("--v"), "2",
"style on activated element");
}
}, `toggle groups test: ${t}`);
}
promise_test(async () => {
container.innerHTML = `
<div id="e" style="toggle: tog [a b] at b self group"></div>
<div id="f" style="toggle: tog [a b] at a self group"></div>
`;
let e = document.getElementById("e");
let f = document.getElementById("f");
await Promise.all([wait_for_toggle_creation(e),
wait_for_toggle_creation(f)]);
let te = e.toggles.get("tog");
let tf = f.toggles.get("tog");
assert_equals(te.value, "b", "e value before first click");
assert_true(e.matches(':toggle(tog b):toggle(tog 1)'),
"e selector matching before first click");
assert_equals(tf.value, "a", "f value before first click");
assert_true(f.matches(':toggle(tog a):toggle(tog 0)'),
"f selector matching before first click");
f.click();
assert_equals(te.value, 0, "e value after first click");
assert_equals(tf.value, "b", "f value after first click");
f.click();
assert_equals(te.value, 0, "e value after second click");
assert_equals(tf.value, "a", "f value after second click");
te.value = "b";
assert_equals(te.value, "b", "e value after first value set");
assert_equals(tf.value, 0, "f value after first value set");
tf.value = "b";
assert_equals(te.value, 0, "e value after second value set");
assert_equals(tf.value, "b", "f value after second value set");
tf.value = "a";
assert_equals(te.value, 0, "e value after third value set");
assert_equals(tf.value, "a", "f value after third value set");
// Swap the order of the state names in 'toggle-root'. This does not affect
// the states on the toggle, but still affects the override specifier used
// in some algorithms.
e.style.toggleRoot = "tog [b a] at 0 self group";
f.style.toggleRoot = "tog [b a] at 0 self group";
await Promise.all([wait_for_toggle_creation(e),
wait_for_toggle_creation(f)]);
assert_equals(te.value, 0, "e value after changing toggle-root");
assert_equals(tf.value, "a", "f value after changing toggle-root");
e.click();
assert_equals(te.value, "a", "e value after third click");
assert_equals(tf.value, 0, "f value after third click");
e.click();
assert_equals(te.value, "b", "e value after fourth click");
assert_equals(tf.value, 0, "f value after fourth click");
assert_true(e.matches(':toggle(tog b):toggle(tog 1)'),
"e selector matching after changing toggle-root");
assert_true(f.matches(':toggle(tog a):toggle(tog 0)'),
"f selector matching after changing toggle-root");
tf.value = "a";
assert_equals(te.value, 0, "e value after fourth value set");
assert_equals(tf.value, "a", "f value after fourth value set");
tf.value = "b";
assert_equals(te.value, 0, "e value after fifth value set");
assert_equals(tf.value, "b", "f value after fifth value set");
te.value = "b";
assert_equals(te.value, "b", "e value after sixth value set");
assert_equals(tf.value, "b", "f value after sixth value set");
}, "zeroing toggle group uses states from override specifier");
// TODO(dbaron): This could probably use a few additional tests for multiple
// values of the list-valued properties. (But they're hard to auto-generate.)
</script>

View file

@ -0,0 +1,489 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: activation of toggles</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#fire-a-toggle-activation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<style>
:toggle(finding-test 0) { --finding-test:0; }
:toggle(finding-test 1) { --finding-test:1; }
:toggle(test-states 0) { --test-states:0; }
:toggle(test-states 1) { --test-states:1; }
:toggle(test-states 2) { --test-states:2; }
:toggle(test-group 0) { --test-group:0; }
:toggle(test-group 1) { --test-group:1; }
:toggle(test-overflow 0) { --test-overflow:0; }
:toggle(test-overflow 1) { --test-overflow:1; }
:toggle(set-num 0) { --set-num:0; }
:toggle(set-num 1) { --set-num:1; }
:toggle(set-num 2) { --set-num:2; }
:toggle(set-names zero) { --set-names:0; }
:toggle(set-names one) { --set-names:1; }
:toggle(set-names two) { --set-names:2; }
:toggle(set-names three) { --set-names:3; }
</style>
<body>
<div id="container"></div>
<script>
let container = document.getElementById("container");
let toggle_finding_tests = [
{
description: "wide toggle on previous sibling",
markup: `<div>
<div id="toggle"></div>
<div id="target"></div>
</div>`,
found: true
},
{
description: "narrow toggle on previous sibling",
markup: `<div>
<div id="toggle"></div>
<div id="target"></div>
</div>`,
found: false,
self: true
},
{
description: "wide toggle on previous sibling with intervening narrow toggle",
markup: `<div>
<div id="toggle"></div>
<div style="toggle: finding-test self"></div>
<div id="target"></div>
</div>`,
found: true
},
{
description: "wide toggle on parent with intervening narrow toggle",
markup: `<div id="toggle">
<div style="toggle: finding-test self"></div>
<div id="target"></div>
</div>`,
found: true
},
{
description: "wide toggle on parent's prior sibling with intervening narrow toggle",
markup: `<div id="toggle"></div>
<div>
<div style="toggle: finding-test self"></div>
<div id="target"></div>
</div>`,
found: true
},
{
description: "wide toggle on later sibling",
markup: `<div id="target"></div>
<div id="toggle"></div>`,
found: false
},
{
description: "wide toggle on child",
markup: `<div id="target">
<div id="toggle"></div>
</div>`,
found: false
}
];
for (let toggle_finding_test of toggle_finding_tests) {
promise_test(async function() {
container.innerHTML = toggle_finding_test.markup;
let toggle = document.getElementById("toggle");
let toggle_cs = getComputedStyle(toggle);
let target = document.getElementById("target");
let toggle_root_style = "finding-test";
if (toggle_finding_test.self) {
toggle_root_style += " self";
}
toggle.style.toggleRoot = toggle_root_style;
target.style.toggleTrigger = "finding-test";
await wait_for_toggle_creation(toggle);
assert_true(toggle.matches(':toggle(finding-test 0)'),
"matches before click");
assert_equals(toggle_cs.getPropertyValue("--finding-test"), "0",
"computed style before click");
target.click();
if (toggle_finding_test.found) {
assert_true(toggle.matches(':toggle(finding-test 1)'),
"matches after click");
assert_equals(toggle_cs.getPropertyValue("--finding-test"), "1",
"computed style after click");
} else {
assert_true(toggle.matches(':toggle(finding-test 0)'),
"matches after click");
assert_equals(toggle_cs.getPropertyValue("--finding-test"), "0",
"computed style after click");
}
}, `finding toggle: ${toggle_finding_test.description}`);
}
promise_test(async function() {
let e = await set_up_single_toggle_in(container, "test-states 1 at 0");
let cs = getComputedStyle(e);
assert_true(e.matches(":toggle(test-states 0)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.click();
assert_true(e.matches(":toggle(test-states 1)"));
assert_equals(cs.getPropertyValue("--test-states"), "1");
e.click();
assert_true(e.matches(":toggle(test-states 0)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.style.toggleRoot = "test-states 2 at 2";
await wait_for_toggle_creation(e);
assert_true(e.matches(":toggle(test-states 0)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.click();
e.click();
assert_true(e.matches(":toggle(test-states 2)"));
assert_equals(cs.getPropertyValue("--test-states"), "2");
e.style.toggleRoot = "";
await wait_for_toggle_creation(e);
assert_true(e.matches(":toggle(test-states 2)"));
assert_equals(cs.getPropertyValue("--test-states"), "2");
e.click();
assert_true(e.matches(":toggle(test-states 0)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.click();
assert_true(e.matches(":toggle(test-states 1)"));
assert_equals(cs.getPropertyValue("--test-states"), "1");
e.click();
assert_true(e.matches(":toggle(test-states 0)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
}, "states used from toggle or toggle specifier as appropriate (integer)");
promise_test(async function() {
let e = await set_up_single_toggle_in(container, "test-states [one two] at 0");
let cs = getComputedStyle(e);
let t = e.toggles.get("test-states");
assert_equals(t.value, 0);
assert_true(e.matches(":toggle(test-states 0)"));
assert_true(e.matches(":toggle(test-states one)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.click();
assert_equals(t.value, "two");
assert_true(e.matches(":toggle(test-states 1)"));
assert_true(e.matches(":toggle(test-states two)"));
assert_equals(cs.getPropertyValue("--test-states"), "1");
e.click();
assert_equals(t.value, "one");
assert_true(e.matches(":toggle(test-states 0)"));
assert_true(e.matches(":toggle(test-states one)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.style.toggleRoot = "test-states [zero one two] at 2";
await wait_for_toggle_creation(e);
assert_equals(t.value, "one");
assert_true(e.matches(":toggle(test-states 0)"));
assert_true(e.matches(":toggle(test-states one)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.click();
assert_equals(t.value, "two");
assert_true(e.matches(":toggle(test-states 1)"));
assert_true(e.matches(":toggle(test-states two)"));
assert_equals(cs.getPropertyValue("--test-states"), "1");
e.click();
assert_equals(t.value, "zero");
assert_true(e.matches(":toggle(test-states zero)"));
assert_equals(cs.getPropertyValue("--test-states"), "");
e.style.toggleRoot = "";
await wait_for_toggle_creation(e);
assert_equals(t.value, "zero");
assert_true(e.matches(":toggle(test-states zero)"));
assert_equals(cs.getPropertyValue("--test-states"), "");
e.click();
assert_equals(t.value, "one");
assert_true(e.matches(":toggle(test-states 0)"));
assert_true(e.matches(":toggle(test-states one)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
e.click();
assert_equals(t.value, "two");
assert_true(e.matches(":toggle(test-states 1)"));
assert_true(e.matches(":toggle(test-states two)"));
assert_equals(cs.getPropertyValue("--test-states"), "1");
e.click();
assert_equals(t.value, "one");
assert_true(e.matches(":toggle(test-states 0)"));
assert_true(e.matches(":toggle(test-states one)"));
assert_equals(cs.getPropertyValue("--test-states"), "0");
}, "states used from toggle or toggle specifier as appropriate (names)");
promise_test(async function() {
container.innerHTML = `
<div style="toggle-group: test-group">
<div id="t" style="toggle: test-group 1 at 0 group"></div>
<div id="other" style="toggle: test-group 1 at 0 group"></div>
</div>
`;
let t = document.getElementById("t");
let other = document.getElementById("other");
let t_cs = getComputedStyle(t);
let other_cs = getComputedStyle(other);
await wait_for_toggle_creation(t);
await wait_for_toggle_creation(other);
other.click();
assert_true(t.matches(":toggle(test-group 0)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "0");
assert_true(other.matches(":toggle(test-group 1)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "1");
t.click();
assert_true(t.matches(":toggle(test-group 1)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "1");
assert_true(other.matches(":toggle(test-group 0)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "0");
other.click();
assert_true(t.matches(":toggle(test-group 0)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "0");
assert_true(other.matches(":toggle(test-group 1)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "1");
// Test that we use the group value from the toggle specifier when it's
// different from the toggle, but only when that's the toggle we're
// changing.
t.style.toggleRoot = "test-group 1 at 0";
t.click();
assert_true(t.matches(":toggle(test-group 1)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "1");
assert_true(other.matches(":toggle(test-group 1)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "1");
other.click();
assert_true(t.matches(":toggle(test-group 1)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "1");
assert_true(other.matches(":toggle(test-group 0)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "0");
other.click();
assert_true(t.matches(":toggle(test-group 0)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "0");
assert_true(other.matches(":toggle(test-group 1)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "1");
// Test that we use the group value from the toggle when there is no toggle
// specifier.
t.style.toggleRoot = "";
t.click();
assert_true(t.matches(":toggle(test-group 1)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "1");
assert_true(other.matches(":toggle(test-group 0)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "0");
other.click();
assert_true(t.matches(":toggle(test-group 0)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "0");
assert_true(other.matches(":toggle(test-group 1)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "1");
other.click();
assert_true(t.matches(":toggle(test-group 0)"));
assert_equals(t_cs.getPropertyValue("--test-group"), "0");
assert_true(other.matches(":toggle(test-group 0)"));
assert_equals(other_cs.getPropertyValue("--test-group"), "0");
}, "group used from toggle or toggle specifier as appropriate");
promise_test(async function() {
let e = await set_up_single_toggle_in(container, "test-overflow sticky");
let cs = getComputedStyle(e);
assert_true(e.matches(":toggle(test-overflow 0)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "0");
e.click();
assert_true(e.matches(":toggle(test-overflow 1)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "1");
e.click();
assert_true(e.matches(":toggle(test-overflow 1)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "1");
e.style.toggleRoot = "test-overflow";
await wait_for_toggle_creation(e);
assert_true(e.matches(":toggle(test-overflow 1)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "1");
e.click();
assert_true(e.matches(":toggle(test-overflow 0)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "0");
e.style.toggleRoot = "";
await wait_for_toggle_creation(e);
assert_true(e.matches(":toggle(test-overflow 0)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "0");
e.click();
assert_true(e.matches(":toggle(test-overflow 1)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "1");
e.click();
assert_true(e.matches(":toggle(test-overflow 1)"));
assert_equals(cs.getPropertyValue("--test-overflow"), "1");
}, "overflow used from toggle or toggle specifier as appropriate");
promise_test(async function() {
container.innerHTML = `<div id="t" style="toggle-root: set-num 5 at 1"></div>
<div id="a" style="toggle-trigger: set-num set 2"></div>
<div id="b" style="toggle-trigger: set-num set 0"></div>
<div id="c" style="toggle-trigger: set-num set named-state"></div>
<div id="m"></div>
`;
let t = document.getElementById("t");
let a = document.getElementById("a");
let b = document.getElementById("b");
let c = document.getElementById("c");
let m = document.getElementById("m");
let cs = getComputedStyle(m);
await wait_for_toggle_creation(t);
assert_true(m.matches(':toggle(set-num 1)'), "initial state");
assert_equals(cs.getPropertyValue("--set-num"), "1");
a.click();
assert_true(m.matches(':toggle(set-num 2)'), "state after clicking a");
assert_equals(cs.getPropertyValue("--set-num"), "2");
b.click();
assert_true(m.matches(':toggle(set-num 0)'), "state after clicking b");
assert_equals(cs.getPropertyValue("--set-num"), "0");
c.click();
assert_true(m.matches(':toggle(set-num named-state)'), "state after clicking c");
assert_equals(cs.getPropertyValue("--set-num"), "");
}, "changing with toggle-trigger: set (numbers)");
promise_test(async function() {
container.innerHTML = `<div id="t" style="toggle-root: set-names [zero one two three four five] at two"></div>
<div id="a" style="toggle-trigger: set-names set one"></div>
<div id="b" style="toggle-trigger: set-names set 3"></div>
<div id="c" style="toggle-trigger: set-names set zero"></div>
<div id="d" style="toggle-trigger: set-names set named-state"></div>
<div id="m"></div>
`;
let t = document.getElementById("t");
let a = document.getElementById("a");
let b = document.getElementById("b");
let c = document.getElementById("c");
let d = document.getElementById("d");
let m = document.getElementById("m");
let cs = getComputedStyle(m);
await wait_for_toggle_creation(t);
assert_true(m.matches(':toggle(set-names two)'));
assert_true(m.matches(':toggle(set-names 2)'));
assert_equals(cs.getPropertyValue("--set-names"), "2");
a.click();
assert_true(m.matches(':toggle(set-names one)'));
assert_true(m.matches(':toggle(set-names 1)'));
assert_equals(cs.getPropertyValue("--set-names"), "1");
b.click();
assert_true(m.matches(':toggle(set-names three)'));
assert_true(m.matches(':toggle(set-names 3)'));
assert_equals(cs.getPropertyValue("--set-names"), "3");
c.click();
assert_true(m.matches(':toggle(set-names zero)'));
assert_true(m.matches(':toggle(set-names 0)'));
assert_equals(cs.getPropertyValue("--set-names"), "0");
d.click();
assert_true(m.matches(':toggle(set-names named-state)'));
assert_false(m.matches(':toggle(set-names 0)'));
assert_equals(cs.getPropertyValue("--set-names"), "");
b.click();
assert_true(m.matches(':toggle(set-names 3)'));
assert_equals(cs.getPropertyValue("--set-names"), "3");
d.click();
assert_false(m.matches(':toggle(set-names 3)'));
assert_equals(cs.getPropertyValue("--set-names"), "");
}, "changing with toggle-trigger: set (named states)");
function test_action_and_cycle(states_and_cycle, start, action, result) {
promise_test(async function() {
container.innerHTML = `
<div id="toggle" style="toggle-root: test ${states_and_cycle}"></div>
<div id="start" style="toggle-trigger: test set ${start}"></div>
<div id="action" style="toggle-trigger: test ${action}"></div>
`;
let toggle = document.getElementById("toggle");
await wait_for_toggle_creation(toggle);
document.getElementById("start").click();
assert_true(toggle.matches(`:toggle(test ${start})`), "value after set");
document.getElementById("action").click();
assert_true(toggle.matches(`:toggle(test ${result})`), "value after action");
}, `toggle with "${states_and_cycle}" changing from "${start}" with action "${action}"`);
}
function test_action_and_all_cycles(states, start, action, result_cycle, result_cycle_on, result_sticky) {
test_action_and_cycle(states, start, action, result_cycle);
test_action_and_cycle(`${states} cycle`, start, action, result_cycle);
test_action_and_cycle(`${states} cycle-on`, start, action, result_cycle_on);
test_action_and_cycle(`${states} sticky`, start, action, result_sticky);
}
test_action_and_all_cycles("2", "0", "next", "1", "1", "1");
test_action_and_all_cycles("2", "1", "next", "2", "2", "2");
test_action_and_all_cycles("2", "2", "next", "0", "1", "2");
test_action_and_all_cycles("3", "5", "next", "0", "1", "3");
test_action_and_all_cycles("4", "3", "next", "4", "4", "4");
test_action_and_all_cycles("4", "3", "next 3", "0", "1", "4");
test_action_and_all_cycles("3", "named-value", "next", "0", "1", "3");
test_action_and_all_cycles("[a b c d]", "a", "next", "b", "b", "b");
test_action_and_all_cycles("[a b c d]", "a", "next 5", "a", "b", "d");
test_action_and_all_cycles("[a b c d]", "c", "next", "d", "d", "d");
test_action_and_all_cycles("[a b c d]", "d", "next", "a", "b", "d");
test_action_and_all_cycles("[a b c d]", "extra-state", "next", "a", "b", "d");
test_action_and_all_cycles("2", "0", "prev", "2", "2", "0");
test_action_and_all_cycles("2", "1", "prev", "0", "2", "0");
test_action_and_all_cycles("2", "2", "prev", "1", "1", "1");
test_action_and_all_cycles("2", "5", "prev", "2", "2", "2");
test_action_and_all_cycles("3", "5", "prev 3", "2", "2", "2");
test_action_and_all_cycles("3", "2", "prev 3", "3", "3", "0");
test_action_and_all_cycles("3", "named-value", "prev", "3", "3", "3");
test_action_and_all_cycles("[a b c d]", "a", "prev", "d", "d", "a");
test_action_and_all_cycles("[a b c d]", "b", "prev", "a", "d", "a");
test_action_and_all_cycles("[a b c d]", "d", "prev", "c", "c", "c");
test_action_and_all_cycles("[a b c d]", "c", "prev 5", "d", "d", "a");
test_action_and_all_cycles("[a b c d]", "extra-state", "prev", "d", "d", "d");
// TODO(https://github.com/tabatkins/css-toggle/issues/39): This set of
// tests is testing proposed behavior; the spec currently says something
// that we agree is wrong.
promise_test(async function() {
container.innerHTML = `
<button id="toggle" style="toggle: test"></button>
`;
let toggle = document.getElementById("toggle");
await wait_for_toggle_creation(toggle);
assert_true(!toggle.matches(`:toggle(test)`), "value before click");
toggle.click();
assert_true(toggle.matches(`:toggle(test)`), "value after click");
}, "toggle activation on button with toggle-trigger (1)");
promise_test(async function() {
container.innerHTML = `
<div id="toggle" style="toggle-root: test">
<button id="trigger" style="toggle-trigger: test"></button>
</div>
`;
let toggle = document.getElementById("toggle");
await wait_for_toggle_creation(toggle);
assert_true(!toggle.matches(`:toggle(test)`), "value before click");
document.getElementById("trigger").click();
assert_true(toggle.matches(`:toggle(test)`), "value after click");
}, "toggle activation on button with toggle-trigger (2)");
promise_test(async function() {
container.innerHTML = `
<div id="toggle" style="toggle: test">
<button id="button"></button>
</div>
`;
let toggle = document.getElementById("toggle");
await wait_for_toggle_creation(toggle);
assert_true(!toggle.matches(`:toggle(test)`), "value before click");
document.getElementById("button").click();
assert_true(!toggle.matches(`:toggle(test)`), "value after button click");
toggle.click();
assert_true(toggle.matches(`:toggle(test)`), "value after div click");
}, "toggle activation on button inside element with toggle-trigger");
promise_test(async function() {
container.innerHTML = `
<div id="toggle" style="toggle: test">
<div id="div"></div>
</div>
`;
let toggle = document.getElementById("toggle");
await wait_for_toggle_creation(toggle);
assert_true(!toggle.matches(`:toggle(test)`), "value before click");
document.getElementById("div").click();
assert_true(toggle.matches(`:toggle(test)`), "value after inner div click");
toggle.click();
assert_true(!toggle.matches(`:toggle(test)`), "value after outer div click");
}, "toggle activation on div inside element with toggle-trigger");
</script>

View file

@ -0,0 +1,338 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: CSSToggle and CSSToggleMap API</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#dom">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<div id="test"></div>
<script>
let container = document.getElementById("test");
promise_test(async function() {
container.innerHTML = `
<style>
:toggle(mytoggle) { --t:4; }
:toggle(newtoggle) { --t:7; }
:toggle(newname) { --t:9; }
</style>
<div>
<div id="a" style="toggle-root: mytoggle 2 at 1 self"></div>
</div>
<div>
<div id="b"></div>
</div>
`;
let a = document.getElementById("a");
let b = document.getElementById("b");
assert_equals(a.toggles.size, 0, "a.toggles.size before creation");
assert_equals(b.toggles.size, 0, "b.toggles.size before creation");
await wait_for_toggle_creation(a);
assert_equals(a.toggles.size, 1, "a.toggles.size after creation");
assert_equals(b.toggles.size, 0, "b.toggles.size after creation");
let t = a.toggles.get("mytoggle");
for (let item of a.toggles) {
assert_equals(item[0], "mytoggle", "iteration of a.toggles");
assert_equals(item[1], t, "iteration of a.toggles");
}
for (let item of a.toggles.entries()) {
assert_equals(item[0], "mytoggle", "iteration of a.toggles.entries()");
assert_equals(item[1], t, "iteration of a.toggles.entries()");
}
for (let item of a.toggles.keys()) {
assert_equals(item, "mytoggle", "iteration of a.toggles.keys()");
}
for (let item of a.toggles.values()) {
assert_equals(item, t, "iteration of a.toggles.values()");
}
assert_equals(Object.getPrototypeOf(a.toggles), CSSToggleMap.prototype);
assert_equals(Object.getPrototypeOf(t), CSSToggle.prototype);
let computed = (element) => getComputedStyle(element).getPropertyValue("--t");
assert_equals(computed(a), "4", "computed style before move");
assert_equals(computed(b), "", "computed style before move");
b.toggles.set("newtoggle", t);
assert_equals(a.toggles.size, 0, "a.toggles.size after move");
assert_equals(b.toggles.size, 1, "b.toggles.size after move");
assert_equals(computed(a), "", "computed style after move");
assert_equals(computed(b), "7", "computed style after move");
assert_equals(a.toggles.get("mytoggle"), undefined, 'a.toggles.get("mytoggle") after move');
assert_equals(a.toggles.get("newtoggle"), undefined, 'a.toggles.get("newtoggle") after move');
assert_equals(b.toggles.get("mytoggle"), undefined, 'b.toggles.get("mytoggle") after move');
assert_equals(b.toggles.get("newtoggle"), t, 'b.toggles.get("newtoggle") after move');
b.toggles.set("newname", t);
assert_equals(a.toggles.size, 0, "a.toggles.size after rename");
assert_equals(b.toggles.size, 1, "b.toggles.size after rename");
assert_equals(computed(a), "", "computed style after rename");
assert_equals(computed(b), "9", "computed style after rename");
assert_equals(a.toggles.get("mytoggle"), undefined, 'a.toggles.get("mytoggle") after rename');
assert_equals(a.toggles.get("newtoggle"), undefined, 'a.toggles.get("newtoggle") after rename');
assert_equals(a.toggles.get("newname"), undefined, 'a.toggles.get("newname") after rename');
assert_equals(b.toggles.get("mytoggle"), undefined, 'b.toggles.get("mytoggle") after rename');
assert_equals(b.toggles.get("newtoggle"), undefined, 'b.toggles.get("newtoggle") after rename');
assert_equals(b.toggles.get("newname"), t, 'b.toggles.get("newname") after rename');
assert_throws_dom("SyntaxError", () => { a.toggles.set("none", t); },
"setting toggle_name to 'none'");
assert_equals(a.toggles.size, 0, "a.toggles.size after failed set");
assert_equals(b.toggles.size, 1, "b.toggles.size after failed set");
assert_equals(b.toggles.get("newname"), t, "b.toggles.get after failed set");
assert_throws_dom("SyntaxError", () => { let t = new CSSToggle({ "states": [] }); },
"toggle constructor with empty list of states");
assert_throws_dom("SyntaxError", () => { let t = new CSSToggle({ "states": ["one"] }); },
"toggle constructor with only one state");
assert_throws_dom("SyntaxError", () => { let t = new CSSToggle({ "states": ["one", "two", "one"] }); },
"toggle constructor with duplicate states");
let c = new CSSToggle({ "states": ["one", "two", "three"] });
assert_throws_dom("SyntaxError", () => { c.states = []; },
"toggle states setter with empty list of states");
assert_throws_dom("SyntaxError", () => { c.states = ["one"]; },
"toggle states setter with only one state");
assert_throws_dom("SyntaxError", () => { c.states = ["one", "two", "one"]; },
"toggle states setter with duplicate states");
// TODO(https://crbug.com/1250716): Should the toggle on a be
// re-created at some point? If so, when?
}, "CSSToggleMap basic API usage and moving toggle");
promise_test(async function() {
container.innerHTML = `
<style>
:toggle(mytoggle 0) { --t:0; }
:toggle(mytoggle 1) { --t:1; }
:toggle(mytoggle 2) { --t:2; }
:toggle(mytoggle 3) { --t:3; }
:toggle(mytoggle 4) { --t:4; }
</style>
<div id="a" style="toggle: mytoggle 2 at 1 self"></div>
<div id="b"></div>
`;
let a = document.getElementById("a");
let b = document.getElementById("b");
let computed = (elt) => getComputedStyle(elt).getPropertyValue("--t");
await wait_for_toggle_creation(a);
let t = a.toggles.get("mytoggle");
assert_equals(computed(a), "1", "initial state of toggle");
assert_equals(t.value, 1, "CSSToggle.value in initial state");
assert_equals(t.valueAsNumber, 1, "CSSToggle.valueAsNumber in initial state");
assert_equals(t.valueAsString, null, "CSSToggle.valueAsString in initial state");
assert_equals(t.states, 2, "CSSToggle.states in initial state");
assert_equals(t.group, false, "CSSToggle.group in initial state");
assert_equals(t.scope, "narrow", "CSSToggle.scope in initial state");
assert_equals(t.cycle, "cycle", "CSSToggle.cycle in initial state");
a.click();
assert_equals(computed(a), "2", "state of toggle after click");
assert_equals(t.value, 2, "CSSToggle.value after click");
assert_equals(t.valueAsNumber, 2, "CSSToggle.valueAsNumber after click");
assert_equals(t.valueAsString, null, "CSSToggle.valueAsString after click");
t.value = 1;
assert_equals(computed(a), "1", "state after setting value");
assert_equals(t.value, 1, "CSSToggle.value after setting value");
assert_equals(t.valueAsNumber, 1, "CSSToggle.valueAsNumber after setting value");
assert_equals(t.valueAsString, null, "CSSToggle.valueAsString after setting value");
t.states = ["zero", "one", "two", "three", "four"]
assert_equals(computed(a), "1", "state after setting states");
assert_equals(t.value, 1, "CSSToggle.value after setting states");
assert_equals(t.valueAsNumber, 1, "CSSToggle.valueAsNumber after setting states");
assert_equals(t.valueAsString, "one", "CSSToggle.valueAsString after setting states");
t.value = "three";
assert_equals(computed(a), "3", "state after changing value with new states");
assert_equals(t.value, "three", "CSSToggle.value after changing value with new states");
assert_equals(t.valueAsNumber, 3, "CSSToggle.valueAsNumber after changing value with new states");
assert_equals(t.valueAsString, "three", "CSSToggle.valueAsString after changing value with new states");
// dynamic changes to group are tested in a separate test below
assert_equals(computed(a), "3", "a state before changing scope");
assert_equals(computed(b), "", "b state before changing scope");
t.scope = "wide";
assert_equals(computed(a), "3", "a state after changing scope");
assert_equals(computed(b), "3", "b state after changing scope");
t.scope = "narrow";
assert_equals(computed(a), "3", "a state after changing scope again");
assert_equals(computed(b), "", "b state after changing scope again");
t.value = 4;
assert_equals(computed(a), "4", "state after changing value again")
a.click();
assert_equals(computed(a), "0", "state after cycling with initial cycle")
t.value = 4;
t.cycle = "cycle-on";
assert_equals(computed(a), "4", "state after changing cycle to cycle-on, with toggle-root still set")
a.click();
assert_equals(computed(a), "0", "state after cycling with cycle-on, with toggle-root still set")
// now remove the toggle-root property so that it no longer overrides the
// toggle when changing a toggle.
a.style.toggleRoot = "";
t.value = 4;
t.cycle = "cycle-on";
assert_equals(computed(a), "4", "state after changing cycle to cycle-on")
a.click();
assert_equals(computed(a), "1", "state after cycling with cycle-on")
t.value = 4;
t.cycle = "sticky";
assert_equals(computed(a), "4", "state after changing cycle to sticky")
a.click();
assert_equals(computed(a), "4", "state after cycling with sticky")
t.value = 4;
t.cycle = "cycle";
assert_equals(computed(a), "4", "state after changing cycle to cycle")
a.click();
assert_equals(computed(a), "0", "state after cycling with cycle")
}, "CSSToggle basic API usage on existing toggle");
promise_test(async function() {
container.innerHTML = `
<style>
:toggle(grouptoggle 0) { --g:0; }
:toggle(grouptoggle 1) { --g:1; }
:toggle(grouptoggle 2) { --g:2; }
</style>
<!-- use the document-wide implicit toggle group -->
<div id="a" style="toggle: grouptoggle 2 at 1 self cycle-on"></div>
<div id="b" style="toggle: grouptoggle 2 at 1 self cycle-on"></div>
`;
let a = document.getElementById("a");
let b = document.getElementById("b");
let computed = (elt) => getComputedStyle(elt).getPropertyValue("--g");
await wait_for_toggle_creation(a);
await wait_for_toggle_creation(b);
let ta = a.toggles.get("grouptoggle");
let tb = b.toggles.get("grouptoggle");
assert_equals(computed(a), "1", "initial state of a");
assert_equals(computed(b), "1", "initial state of b");
assert_equals(ta.group, false, "initial group of a");
assert_equals(tb.group, false, "initial group of b");
// Remove the toggle-root property so it doesn't override the group
// on the toggle.
a.style.toggleRoot = "";
b.style.toggleRoot = "";
ta.group = true;
a.click();
assert_equals(computed(a), "2", "state of a after first click");
assert_equals(computed(b), "1", "state of b after first click");
tb.group = true;
assert_equals(computed(a), "2", "state of a after both in group");
assert_equals(computed(b), "1", "state of b after both in group");
a.click();
assert_equals(computed(a), "1", "state of a after second click");
assert_equals(computed(b), "0", "state of b after second click");
b.click();
assert_equals(computed(a), "0", "state of a after third click");
assert_equals(computed(b), "1", "state of b after third click");
ta.group = false;
a.click();
assert_equals(computed(a), "1", "state of a after fourth click");
assert_equals(computed(b), "1", "state of b after fourth click");
ta.group = true;
tb.group = true;
a.click();
assert_equals(computed(a), "2", "state of a after fifth click");
assert_equals(computed(b), "0", "state of b after fifth click");
// Put the toggle-root property back so that it overrides the group
// on the toggle, but only when changing *that* toggle.
b.style.toggleRoot = "grouptoggle 2 at 1 self cycle-on";
b.click();
assert_equals(computed(a), "2", "state of a after sixth click");
assert_equals(computed(b), "1", "state of b after sixth click");
a.click();
assert_equals(computed(a), "1", "state of a after seventh click");
assert_equals(computed(b), "0", "state of b after seventh click");
}, "CSSToggle usage of group setter on existing toggle");
promise_test(async function() {
container.innerHTML = `
<style>
:toggle(d 0) { --d:0; }
:toggle(d 1) { --d:1; }
:toggle(d 2) { --d:2; }
:toggle(e 0) { --e:0; }
:toggle(e 1) { --e:1; }
:toggle(e 2) { --e:2; }
:toggle(f 0) { --f:0; }
:toggle(f 1) { --f:1; }
:toggle(f 2) { --f:2; }
</style>
<div id="a"></div>
<!-- TODO(https://crbug.com/1250716): This toggle-trigger should probably
also work if I set it dynamically right before the first click. -->
<div id="b" style="toggle-trigger: d next, e prev"></div>
`;
let a = document.getElementById("a");
let b = document.getElementById("b");
assert_equals(a.toggles.size, 0, "a.toggles.size before creation");
assert_equals(b.toggles.size, 0, "b.toggles.size before creation");
let computed = (elt, prop) => getComputedStyle(elt).getPropertyValue(`--${prop}`);
assert_equals(computed(a, "d"), "", "initial computed(a, d)");
assert_equals(computed(a, "e"), "", "initial computed(a, e)");
assert_equals(computed(b, "d"), "", "initial computed(b, d)");
assert_equals(computed(b, "e"), "", "initial computed(b, e)");
let t1 = new CSSToggle({states: 2, cycle: "cycle-on"});
let t2 = new CSSToggle({states: 2, value: 1, scope: "narrow"});
a.toggles.set("d", t1);
assert_equals(a.toggles.size, 1, "step 2 a.toggles.size");
assert_equals(b.toggles.size, 0, "step 2 b.toggles.size");
assert_equals(computed(a, "d"), "0", "step 2 computed(a, d)");
assert_equals(computed(b, "d"), "0", "step 2 computed(b, d)");
assert_equals(computed(a, "e"), "", "step 2 computed(a, e)");
assert_equals(computed(b, "e"), "", "step 2 computed(b, e)");
b.toggles.set("e", t2);
assert_equals(a.toggles.size, 1, "step 3 a.toggles.size");
assert_equals(b.toggles.size, 1, "step 3 b.toggles.size");
assert_equals(computed(a, "d"), "0", "step 3 computed(a, d)");
assert_equals(computed(b, "d"), "0", "step 3 computed(b, d)");
assert_equals(computed(a, "e"), "", "step 3 computed(a, e)");
assert_equals(computed(b, "e"), "1", "step 3 computed(b, e)");
b.click();
assert_equals(computed(a, "d"), "1", "step 4 computed(a, d)");
assert_equals(computed(b, "d"), "1", "step 4 computed(b, d)");
assert_equals(computed(a, "e"), "", "step 4 computed(a, e)");
assert_equals(computed(b, "e"), "0", "step 4 computed(b, e)");
a.toggles.set("f", t2);
assert_equals(a.toggles.size, 2, "step 5 a.toggles.size");
assert_equals(b.toggles.size, 0, "step 5 b.toggles.size");
assert_equals(computed(a, "d"), "1", "step 5 computed(a, d)");
assert_equals(computed(b, "d"), "1", "step 5 computed(b, d)");
assert_equals(computed(a, "e"), "", "step 5 computed(a, e)");
assert_equals(computed(b, "e"), "", "step 5 computed(b, e)");
assert_equals(computed(a, "f"), "0", "step 5 computed(a, f)");
assert_equals(computed(b, "f"), "", "step 5 computed(b, f)");
b.click();
assert_equals(computed(a, "d"), "2", "step 6 computed(a, d)");
assert_equals(computed(b, "d"), "2", "step 6 computed(b, d)");
assert_equals(computed(a, "e"), "", "step 6 computed(a, e)");
assert_equals(computed(b, "e"), "", "step 6 computed(b, e)");
assert_equals(computed(a, "f"), "0", "step 6 computed(a, f)");
assert_equals(computed(b, "f"), "", "step 6 computed(b, f)");
}, "dynamic creation of CSSToggle and their use");
</script>

View file

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: creation of toggles</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-root-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<body>
<div id="container"></div>
<script>
let container = document.getElementById("container");
promise_test(async () => {
container.innerHTML = '<div id="t" style="toggle: mytoggle"></div>';
let t = document.getElementById("t");
await wait_for_toggle_creation(t);
assert_false(t.matches(':toggle(mytoggle)'));
assert_true(t.matches(':toggle(mytoggle 0)'));
assert_false(t.matches(':toggle(mytoggle 1)'));
t.click();
assert_true(t.matches(':toggle(mytoggle)'));
assert_false(t.matches(':toggle(mytoggle 0)'));
assert_true(t.matches(':toggle(mytoggle 1)'));
t.click();
assert_true(t.matches(':toggle(mytoggle 0)'));
assert_false(t.matches(':toggle(mytoggle 1)'));
}, "basic toggle creation");
promise_test(async () => {
// Test that changing the toggle-root property to add 'self' doesn't change
// the toggle's scope from wide to narrow.
container.innerHTML = `
<div id="a" style="toggle-root: changing-scope 3 at 2">
<div id="b" style="toggle-trigger: changing-scope"></div>
</div>
<div id="c"></div>
`;
let a = document.getElementById("a");
let b = document.getElementById("b");
let c = document.getElementById("c");
await wait_for_toggle_creation(a);
assert_true(b.matches(':toggle(changing-scope 2)'));
assert_true(c.matches(':toggle(changing-scope 2)'));
a.style.toggleRoot = "changing-scope 3 at 2 self";
await wait_for_toggle_creation(a);
assert_true(b.matches(':toggle(changing-scope 2)'));
assert_true(c.matches(':toggle(changing-scope 2)'));
// The reverse -- removing 'self'.
container.innerHTML = `
<div id="a" style="toggle-root: changing-scope 3 at 2 self">
<div id="b" style="toggle-trigger: changing-scope"></div>
</div>
<div id="c"></div>
`;
a = document.getElementById("a");
b = document.getElementById("b");
c = document.getElementById("c");
await wait_for_toggle_creation(a);
assert_true(b.matches(':toggle(changing-scope 2)'));
assert_false(c.matches(':toggle(changing-scope 2)'));
a.style.toggleRoot = "changing-scope 3 at 2";
await wait_for_toggle_creation(a);
assert_true(b.matches(':toggle(changing-scope 2)'));
assert_false(c.matches(':toggle(changing-scope 2)'));
}, "changing toggle-root doesn't change toggle");
</script>

View file

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: CSSToggle and CSSToggleMap API</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#csstoggleevent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<div id="test"></div>
<script>
let container = document.getElementById("test");
function click_while_waiting_for_togglechange(event_watcher, element) {
let p = event_watcher.wait_for("togglechange");
element.click();
return p;
}
promise_test(async test => {
container.innerHTML = `
<div id="element" style="toggle: mytoggle 2 at 1 self sticky"></div>
`;
const element = document.getElementById("element");
await wait_for_toggle_creation(element);
let toggle = element.toggles.get("mytoggle");
assert_equals(toggle.value, 1, "initial value of toggle");
const watcher = new EventWatcher(test, element, [ "togglechange" ]);
await click_while_waiting_for_togglechange(watcher, element).then(ev => {
assert_equals(Object.getPrototypeOf(ev), CSSToggleEvent.prototype);
assert_equals(ev.toggleName, "mytoggle", "event.toggleName after first change");
assert_equals(ev.toggle, toggle, "event.toggle after first change");
assert_equals(toggle.value, 2, "value after first change");
});
// Test that the event does not fire when the toggle doesn't change due to
// being "sticky" and stuck. EventWatcher will assert if there is an event.
element.click();
assert_equals(toggle.value, 2, "value after second change");
toggle.value = 0;
// there should be no event; EventWatcher will assert if there is one.
}, "basic toggle event firing");
</script>

View file

@ -0,0 +1,235 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: creation of toggles</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#checked-pseudoclass">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/parsing-testcommon.js"></script>
<script src="support/toggle-helpers.js"></script>
<body>
<div id="container"></div>
<script>
test_valid_selector(":toggle(my-toggle)");
test_valid_selector(":toggle(my-toggle 0)");
test_valid_selector(":toggle(my-toggle 1)");
test_valid_selector(":toggle( my-toggle 1 )", ":toggle(my-toggle 1)");
test_valid_selector(":toggle(my-toggle named-state)");
test_valid_selector(":toggle( my-toggle named-state )", ":toggle(my-toggle named-state)");
test_invalid_selector(":toggle(my-toggle, 0)");
test_invalid_selector(":toggle(my-toggle, named-state)");
test_invalid_selector(":toggle(my-toggle named-state 0)");
// In these tests, the following class attributes lead to markup creation:
// class=toggle, class=toggle-self, class=variant-toggle,
// class=variant-toggle-self. These all lead to the creation of a toggle
// called "markup-test". If "-self" is present then the toggle has narrow
// scope (otherwise wide scope). If "variant-" is present then the toggle has
// a value different from what the primary test assertions target (otherwise
// it is what the test assertions target).
//
// The following class attributes lead to test assertions:
// class=assert-match: Assert the :toggle() selector matches the toggle
// class=assert-no-match: Assert the :toggle() selector does not match the
// toggle.
// class=assert-variant-match: Assert the :toggle() selector matches the
// variant toggle.
let scope_search_tests = [
`
<div>
<div class="assert-no-match"></div>
<div class="toggle assert-match">
<div class="assert-match"></div>
</div>
<div class="assert-match"></div>
</div>
<div class="assert-no-match"></div>
`,
`
<div>
<div class="assert-no-match"></div>
<div class="toggle-self assert-match">
<div class="assert-match"></div>
</div>
<div class="assert-no-match"></div>
</div>
<div class="assert-no-match"></div>
`,
`
<div class="toggle"></div>
<div class="variant-toggle-self">
<div class="assert-variant-match"></div>
</div>
<div class="assert-match"></div>
`,
`
<div class="toggle"></div>
<div class="assert-match"></div>
<div class="variant-toggle">
<div class="assert-variant-match"></div>
</div>
<div class="assert-variant-match"></div>
`,
];
for (let t of scope_search_tests) {
promise_test(async function() {
container.innerHTML = t;
for (let e of container.querySelectorAll(".toggle")) {
e.style.toggleRoot = "scope-test 10 at 3";
}
for (let e of container.querySelectorAll(".toggle-self")) {
e.style.toggleRoot = "scope-test 10 at 3 self";
}
for (let e of container.querySelectorAll(".variant-toggle")) {
e.style.toggleRoot = "scope-test 10 at 8";
}
for (let e of container.querySelectorAll(".variant-toggle-self")) {
e.style.toggleRoot = "scope-test 10 at 8 self";
}
for (let e of container.querySelectorAll(
".toggle, .toggle-self, .variant-toggle, .variant-toggle-self")) {
await wait_for_toggle_creation(e);
}
let assert_match = (e, selector) => {
assert_true(e.matches(selector),
`matches ${selector} (class ${e.className})`);
};
let assert_nomatch = (e, selector) => {
assert_false(e.matches(selector),
`does not match ${selector} (class ${e.className})`);
};
for (let e of container.querySelectorAll(".assert-match")) {
assert_match(e, ":toggle(scope-test)");
assert_match(e, ":toggle(scope-test 3)");
assert_nomatch(e, ":toggle(scope-test 8)");
}
for (let e of container.querySelectorAll(".assert-variant-match")) {
assert_match(e, ":toggle(scope-test)");
assert_nomatch(e, ":toggle(scope-test 3)");
assert_match(e, ":toggle(scope-test 8)");
}
for (let e of container.querySelectorAll(".assert-no-match")) {
assert_nomatch(e, ":toggle(scope-test)");
assert_nomatch(e, ":toggle(scope-test 3)");
assert_nomatch(e, ":toggle(scope-test 8)");
}
}, `scope search test for markup ${t}`);
}
let selector_match_tests = [
{
specifier: [ "my-toggle 2 at 1" ],
matching_selectors: [
":toggle(my-toggle)",
":toggle(my-toggle 1)",
],
not_matching_selectors: [
":toggle(my-toggle 0)",
":toggle(my-toggle 2)",
":toggle(my-toggle named-state)",
],
},
{
specifier: [ "my-toggle 2 at 0" ],
matching_selectors: [
":toggle(my-toggle 0)",
],
not_matching_selectors: [
":toggle(my-toggle)",
":toggle(my-toggle 1)",
":toggle(my-toggle 2)",
":toggle(my-toggle named-state)",
],
},
{
specifier: [ "my-toggle 2 at named-state" ],
matching_selectors: [
":toggle(my-toggle)",
":toggle(my-toggle named-state)",
],
not_matching_selectors: [
":toggle(my-toggle 0)",
":toggle(my-toggle 1)",
":toggle(my-toggle 2)",
":toggle(my-toggle infinite)",
":toggle(my-toggle infinity)",
],
},
{
specifier: [
"my-toggle [a b c d] at 0",
"my-toggle [a b c d] at a",
],
matching_selectors: [
":toggle(my-toggle 0)",
":toggle(my-toggle a)",
],
not_matching_selectors: [
":toggle(my-toggle)",
":toggle(my-toggle 1)",
":toggle(my-toggle 2)",
":toggle(my-toggle b)",
":toggle(my-toggle d)",
":toggle(my-toggle named-state)",
],
},
{
specifier: [
"my-toggle [a b c d] at 1",
"my-toggle [a b c d] at b",
],
matching_selectors: [
":toggle(my-toggle)",
":toggle(my-toggle 1)",
":toggle(my-toggle b)",
],
not_matching_selectors: [
":toggle(my-toggle 0)",
":toggle(my-toggle a)",
":toggle(my-toggle 2)",
":toggle(my-toggle d)",
":toggle(my-toggle named-state)",
],
},
{
specifier: [
"my-toggle [a b c d] at unnamed-state",
],
matching_selectors: [
":toggle(my-toggle)",
":toggle(my-toggle unnamed-state)",
],
not_matching_selectors: [
":toggle(my-toggle 0)",
":toggle(my-toggle a)",
":toggle(my-toggle 1)",
":toggle(my-toggle c)",
":toggle(my-toggle 3)",
],
},
];
for (let t of selector_match_tests) {
for (let specifier of t.specifier) {
promise_test(async function() {
container.innerHTML = `<div style="toggle-root: ${specifier}"></div>`;
let e = container.firstChild;
await wait_for_toggle_creation(e);
for (let sel of t.matching_selectors) {
assert_true(e.matches(sel), `${sel} matches`);
}
for (let sel of t.not_matching_selectors) {
assert_false(e.matches(sel), `${sel} does not match`);
}
}, `:toggle() selector matching tests for ${specifier}`);
}
}
</script>

View file

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: serialization of toggle shorthand</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
let tests = [
{ "toggle-root": null,
"toggle-trigger": "mytoggle",
"expected": "" },
{ "toggle-root": "mytoggle",
"toggle-trigger": null,
"expected": "" },
{ "toggle-root": "none",
"toggle-trigger": "mytoggle",
"expected": "" },
{ "toggle-root": "mytoggle",
"toggle-trigger": "none",
"expected": "" },
{ "toggle-root": "none",
"toggle-trigger": "none",
"expected": "none" },
{ "toggle-root": "mytoggle",
"toggle-trigger": "mytoggle",
"expected": "mytoggle" },
{ "toggle-root": "mytoggle, yourtoggle",
"toggle-trigger": "mytoggle",
"expected": "" },
{ "toggle-root": "mytoggle",
"toggle-trigger": "mytoggle, yourtoggle",
"expected": "" },
{ "toggle-root": "mytoggle 2",
"toggle-trigger": "mytoggle",
"expected": "mytoggle 2" },
{ "toggle-root": "mytoggle 2",
"toggle-trigger": "mytoggle 2",
"expected": "" },
{ "toggle-root": "mytoggle 2 at 1",
"toggle-trigger": "mytoggle",
"expected": "mytoggle 2 at 1" },
{ "toggle-root": "mytoggle 2 at 1",
"toggle-trigger": "mytoggle 1",
"expected": "" },
{ "toggle-root": "mytoggle 2 at 1",
"toggle-trigger": "mytoggle 2",
"expected": "" },
{ "toggle-root": "mytoggle 2 at 1 sticky group self",
"toggle-trigger": "mytoggle",
"expected": "mytoggle 2 at 1 sticky group self" },
{ "toggle-root": "mytoggle 4 at 2 self sticky group",
"toggle-trigger": "mytoggle",
"expected": "mytoggle 4 at 2 sticky group self" },
{ "toggle-root": "mytoggle [one two three] at two self cycle-on group",
"toggle-trigger": "mytoggle",
"expected": "mytoggle [one two three] at two cycle-on group self" },
];
for (let t of tests) {
test(function() {
let element = document.createElement("div");
document.body.appendChild(element);
if (typeof(t["toggle-root"]) == "string")
element.style["toggle-root"] = t["toggle-root"];
if (typeof(t["toggle-trigger"]) == "string")
element.style["toggle-trigger"] = t["toggle-trigger"];
assert_equals(element.style.toggle, t["expected"]);
element.remove();
}, `Serialization of toggle shorthand with${t["toggle-root"] ? (" toggle-root: " + t["toggle-root"] + ";") : ""}${t["toggle-trigger"] ? (" toggle-trigger: " + t["toggle-trigger"] + ";") : ""}`);
}
</script>

View file

@ -0,0 +1,54 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: focusability of elements with toggle-trigger</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="support/toggle-helpers.js"></script>
<div id="test"></div>
<script>
// From shadow-dom/focus/resources/shadow-utils.js
function navigateFocusForward() {
// TAB = '\ue004'
return test_driver.send_keys(document.body, "\ue004");
}
let container = document.getElementById("test");
promise_test(async test => {
container.innerHTML = `
<input id="input" type="text">
<div id="e1" style="toggle-root: tab"></div>
<div id="e2" style="toggle-trigger: tab"></div>
<div id="e3" style="toggle-trigger: tab"></div>
<div id="e4" style="toggle-trigger: nonexistent"></div>
`;
let input = document.getElementById("input");
let e1 = document.getElementById("e1");
let e2 = document.getElementById("e2");
let e3 = document.getElementById("e3");
let e4 = document.getElementById("e4");
await wait_for_toggle_creation(e1);
input.focus();
assert_equals(document.activeElement, input);
await navigateFocusForward();
assert_equals(document.activeElement, e2);
await navigateFocusForward();
assert_equals(document.activeElement, e3);
await navigateFocusForward();
assert_equals(document.activeElement, e4);
}, "elements with toggle-trigger are tabbable");
</script>

View file

@ -0,0 +1,92 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: triggering multiple toggles with a style change</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-trigger-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<div id="test"></div>
<script>
let container = document.getElementById("test");
promise_test(async test => {
container.innerHTML = `
<style>
#t {
toggle-root: t1, t2, t3, t4;
toggle-trigger: t1, t2, t3;
}
</style>
<div id="t"></div>
`;
let t = document.getElementById("t");
await wait_for_toggle_creation(t);
assert_equals(t.toggles.size, 4, "t.toggles.size after creation");
assert_equals(t.toggles.get("t1").value, 0, "t1 after creation");
assert_equals(t.toggles.get("t2").value, 0, "t2 after creation");
assert_equals(t.toggles.get("t3").value, 0, "t3 after creation");
assert_equals(t.toggles.get("t4").value, 0, "t4 after creation");
let event_count = 0;
t.addEventListener("togglechange", event => {
switch (++event_count) {
case 1:
assert_equals(event.toggleName, "t1", "name of first event");
assert_equals(t.toggles.get("t1"), event.toggle);
assert_equals(t.toggles.get("t1").value, 1, "t1 after first event");
assert_equals(t.toggles.get("t2").value, 0, "t2 after first event");
assert_equals(t.toggles.get("t3").value, 0, "t3 after first event");
assert_equals(t.toggles.get("t4").value, 0, "t4 after first event");
break;
case 2:
assert_equals(event.toggleName, "t2", "name of second event");
assert_equals(t.toggles.get("t2"), event.toggle);
assert_equals(t.toggles.get("t1").value, 1, "t1 after second event");
assert_equals(t.toggles.get("t2").value, 1, "t2 after second event");
assert_equals(t.toggles.get("t3").value, 0, "t3 after second event");
assert_equals(t.toggles.get("t4").value, 0, "t4 after second event");
// This changes the value of 'toggle-trigger' in the middle of
// firing the toggle. We want to test that toggles continue firing
// as expected.
//
// It's constructed this way to avoid the old style being cached
// in Chromium's MatchedPropertiesCache, which allows this testcase
// to trigger a crash before the fix that introduced it.
t.previousElementSibling.sheet.cssRules[0].style.toggleTrigger = "t4";
// This assertion is mainly to force the style to be recomputed:
assert_equals(getComputedStyle(t).toggleTrigger, "t4");
break;
case 3:
assert_equals(event.toggleName, "t3", "name of third event");
assert_equals(t.toggles.get("t3"), event.toggle);
assert_equals(t.toggles.get("t1").value, 1, "t1 after third event");
assert_equals(t.toggles.get("t2").value, 1, "t2 after third event");
assert_equals(t.toggles.get("t3").value, 1, "t3 after third event");
assert_equals(t.toggles.get("t4").value, 0, "t4 after third event");
break;
case 4:
assert_equals(event.toggleName, "t4", "name of fourth event");
assert_equals(t.toggles.get("t4"), event.toggle);
assert_equals(t.toggles.get("t1").value, 1, "t1 after fourth event");
assert_equals(t.toggles.get("t2").value, 1, "t2 after fourth event");
assert_equals(t.toggles.get("t3").value, 1, "t3 after fourth event");
assert_equals(t.toggles.get("t4").value, 1, "t4 after fourth event");
break;
default:
assert_unreached("should get four events");
break;
}
});
t.click();
assert_equals(event_count, 3);
t.click();
assert_equals(event_count, 4);
}, "triggering of multiple toggles with a change to toggle-trigger in the middle");
</script>

View file

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: toggle-visibility</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<style>
body {
toggle-root: inactive-toggle 1 at 0;
}
#container {
toggle-visibility: toggle inactive-toggle;
background: green;
width: 100px;
height: 100px;
}
#child, #sibling {
height: 100px;
width: 100px;
background: red;
}
#sibling {
margin-top: -100px;
}
</style>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="container">
<div id="child"></div>
</div>
<div id="sibling"></div>

View file

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: toggle-visibility</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<style>
body {
toggle-root: active-toggle 1 at 1;
}
#container {
toggle-visibility: toggle active-toggle;
background: red;
width: 100px;
height: 100px;
}
#child, #sibling {
height: 100px;
width: 100px;
}
#child {
background: green;
}
#sibling {
background: red;
margin-top: -100px;
}
</style>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="container">
<div id="child"></div>
</div>
<div id="sibling"></div>

View file

@ -0,0 +1,267 @@
<!DOCTYPE HTML>
<meta charset="UTF-8">
<title>CSS Toggles: toggle-visibility</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/toggle-helpers.js"></script>
<style id="style">
</style>
<body>
<div id="container"></div>
<script>
let style = document.getElementById("style");
let container = document.getElementById("container");
promise_test(async function() {
style.innerText = `
#container { toggle-group: t self; }
#t, #t2 { toggle-root: t 1 at 0 group; }
#trigger, #t2 { toggle-trigger: t; }
#vis { toggle-visibility: toggle t; }
#child { height: 100px; }
`;
container.innerHTML = `
<div id="t"></div>
<div id="vis">
<div id="child"></div>
</div>
<div id="trigger"></div>
<div id="t2"></div>
`;
let t = document.getElementById("t");
let trigger = document.getElementById("trigger");
let t2 = document.getElementById("t2");
let vis = document.getElementById("vis");
await wait_for_toggle_creation(t);
const kVisibleHeight = 100;
const kHiddenHeight = 0;
assert_equals(vis.clientHeight, kHiddenHeight, "before first click");
trigger.click();
assert_equals(vis.clientHeight, kVisibleHeight, "after first click");
trigger.click();
assert_equals(vis.clientHeight, kHiddenHeight, "after second click");
t.toggles.get("t").value = 1;
assert_equals(vis.clientHeight, kVisibleHeight, "after toggle value setter");
t2.click();
assert_equals(vis.clientHeight, kHiddenHeight, "after click on other element in group");
}, "showing and hiding in response to toggle changes");
const action_tests = [
{
name: "focus",
markup: `<input type="checkbox" id="check">`,
action: () => {
document.getElementById("check").focus();
},
},
{
name: "scrollIntoView",
markup: `<input type="checkbox" id="check">`,
action: () => {
document.getElementById("check").scrollIntoView();
},
},
];
for (let test of action_tests) {
promise_test(async function() {
style.innerText = `
#container { toggle-group: tab self; }
#tab { toggle: tab 1 at 0 group; }
#panel { toggle-visibility: toggle tab; }
`;
container.innerHTML = `
<div id="tab">Tab</div>
<div id="panel">
${test.markup}
</div>
`;
let tab = document.getElementById("tab");
let panel = document.getElementById("panel");
await wait_for_toggle_creation(tab);
let tab_toggle = tab.toggles.get("tab");
assert_equals(tab_toggle.value, 0, "toggle value before focus");
assert_equals(panel.clientHeight, 0, "panel height before focus");
test.action();
assert_equals(tab_toggle.value, 1, "toggle value after focus");
assert_not_equals(panel.clientHeight, 0, "panel height after focus");
}, `${test.name} inside hidden element changes a toggle to show it`);
}
const scope_tests = [
`
<div class="root-inactive">
<div class="vis expect-hidden"></div>
</div>
<div class="vis expect-hidden"></div>
`,
`
<div class="root-inactive-self">
<div class="vis expect-hidden"></div>
</div>
<div class="vis expect-shown"></div>
`,
`
<div class="root-active">
<div class="vis expect-shown"></div>
</div>
<div class="vis expect-shown"></div>
`,
`
<div class="root-active-self">
<div class="vis expect-shown"></div>
</div>
<div class="vis expect-shown"></div>
`,
];
for (let test of scope_tests) {
promise_test(async function() {
container.innerHTML = test;
style.innerText = `
.root-inactive { toggle-root: t 1 at 0; }
.root-active { toggle-root: t 1 at 1; }
.root-inactive-self { toggle-root: t 1 at 0 self; }
.root-active-self { toggle-root: t 1 at 1 self; }
.vis {
toggle-visibility: toggle t;
}
.vis::before {
content: "";
display: block;
height: 100px;
width: 100px;
}
`;
await wait_for_toggle_creation(container.querySelector('[class^="root-"]'));
for (let e of container.querySelectorAll('.expect-hidden')) {
assert_equals(e.clientHeight, 0);
}
for (let e of container.querySelectorAll('.expect-shown')) {
assert_equals(e.clientHeight, 100);
}
}, `scope test: ${test}`);
}
async function wait_for_content_visibility_auto() {
return new Promise(resolve => {
requestAnimationFrame(() => {
requestAnimationFrame(resolve);
});
});
}
promise_test(async function() {
style.innerText = `
#t { toggle-root: t 1 at 0; }
#vis {
toggle-visibility: toggle t;
content-visibility: auto;
min-height: 50px;
}
#child { height: 100px; }
#spacer { height: 300vh; }
`;
// TODO (dbaron): Why doesn't padding-top on #container have the same effect
// as this spacer?
container.innerHTML = `
<div id="spacer"></div>
<div id="t"></div>
<div id="vis">
<div id="child"></div>
</div>
`;
let t = document.getElementById("t");
let vis = document.getElementById("vis");
let spacer = document.getElementById("spacer");
await wait_for_toggle_creation(t);
let toggle = t.toggles.get("t");
const kVisibleHeight = 100;
const kHiddenHeight = 50;
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and offscreen");
toggle.value = 1;
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle active and offscreen");
spacer.remove();
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and onscreen");
toggle.value = 0;
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and onscreen");
toggle.value = 1;
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and onscreen (2)");
toggle.value = 0;
t.before(spacer);
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and offscreen (2)");
spacer.remove();
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and onscreen (2)");
toggle.value = 1;
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and onscreen (3)");
t.before(spacer);
await wait_for_content_visibility_auto();
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle active and offscreen (2)");
}, "interaction of toggle-visibility and content-visibility: auto");
promise_test(async function() {
style.innerText = `
#t { toggle-root: t 1 at 0; }
#vis {
toggle-visibility: toggle t;
content-visibility: hidden;
}
#child { height: 100px; }
`;
container.innerHTML = `
<div id="t"></div>
<div id="vis">
<div id="child"></div>
</div>
`;
let t = document.getElementById("t");
let vis = document.getElementById("vis");
await wait_for_toggle_creation(t);
let toggle = t.toggles.get("t");
const kVisibleHeight = 100;
const kHiddenHeight = 0;
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and offscreen");
toggle.value = 1;
assert_equals(vis.clientHeight, kHiddenHeight, "with toggle active and offscreen");
}, "interaction of toggle-visibility and content-visibility: hidden");
</script>