Create toggles on elements when specified by the 'toggle-root' property.

(Support for toggles is behind the CSSToggles flag, which is currently
off.)

Bug: 1250716
Change-Id: Ie986a91350de134af837cb4c5e0444ebf9d68e5e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3749645
Reviewed-by: Joey Arhar <jarhar@chromium.org>
Commit-Queue: David Baron <dbaron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1030570}
diff --git a/css/css-toggle/support/toggle-helpers.js b/css/css-toggle/support/toggle-helpers.js
new file mode 100644
index 0000000..972e93f
--- /dev/null
+++ b/css/css-toggle/support/toggle-helpers.js
@@ -0,0 +1,5 @@
+async function wait_for_toggle_creation(element) {
+  // The spec is vague about when toggles need to be created.  Flushing
+  // style is good enough for now, but this might need to change.
+  getComputedStyle(element).toggleRoot;
+}
diff --git a/css/css-toggle/toggle-creation.tentative.html b/css/css-toggle/toggle-creation.tentative.html
new file mode 100644
index 0000000..583e163
--- /dev/null
+++ b/css/css-toggle/toggle-creation.tentative.html
@@ -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>