[menu] move tests to wpt

Explainer:
https://open-ui.org/components/menu.explainer

Intent to Prototype:
https://groups.google.com/a/chromium.org/g/blink-dev/c/C4bw78qLyx8

Change-Id: I31f46f1587081aa56a695e98e9393d118257a080
Bug: 406566432
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6639009
Reviewed-by: Dominic Farolino <dom@chromium.org>
Commit-Queue: Di Zhang <dizhangg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1472631}
diff --git a/html/semantics/menu/tentative/button-invoke-menulist.html b/html/semantics/menu/tentative/button-invoke-menulist.html
new file mode 100644
index 0000000..f5ac3dd
--- /dev/null
+++ b/html/semantics/menu/tentative/button-invoke-menulist.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<button id=btn commandfor="m">Actions</button>
+
+<menulist id=m>
+ <menuitem>Action 1</menuitem>
+ <menuitem>Action 2</menuitem>
+</menulist>
+
+<script>
+const btn = document.getElementById("btn");
+const menulist = document.querySelector("menulist");
+
+test(() => {
+ btn.setAttribute("command", "toggle-popover");
+ btn.disabled = true;
+ btn.click();
+ assert_false(menulist.matches(':popover-open'),
+    'The menulist should not open because the button is disabled.');
+
+ btn.disabled = false;
+ btn.click();
+ assert_true(menulist.matches(':popover-open'),
+    'The menulist should be able to open successfully.');
+ menulist.hidePopover();
+}, "Button with command=toggle-popover can invoke menulist popover.");
+
+test(() => {
+ btn.setAttribute("command", "toggle-menu");
+ btn.disabled = true;
+ btn.click();
+ assert_false(menulist.matches(':popover-open'),
+    'The menulist should not open because the button is disabled.');
+
+ btn.disabled = false;
+ btn.click();
+ assert_true(menulist.matches(':popover-open'),
+    'The menulist should be able to open successfully.');
+ menulist.hidePopover();
+}, "Button with command=toggle-menu can invoke menulist popover.");
+</script>
diff --git a/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html b/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html
new file mode 100644
index 0000000..d41799f
--- /dev/null
+++ b/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<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>
+<link rel=author href=mailto:dizhangg@chromium.org>
+<link rel=help href=https://open-ui.org/components/menu.explainer>
+
+<menubar>
+ <menuitem id=btn commandfor="list" command="toggle-popover">Open</menuitem>
+</menubar>
+
+<menulist id="list">
+ <menuitem id="A1">Command A1</menuitem>
+ <menuitem id="A2">Command A2</menuitem>
+</menulist>
+
+<menubar id="bar">
+  <menuitem id="B1">Command B1</menuitem>
+  <menuitem id="B2">Command B2</menuitem>
+</menubar>
+
+
+<script>
+
+const Enter = '\uE007';
+const Tab = '\uE004';
+const ArrowLeft = '\uE012';
+const ArrowUp = '\uE013';
+const ArrowRight = '\uE014';
+const ArrowDown = '\uE015';
+
+promise_test(async (t) => {
+  await test_driver.send_keys(document.activeElement, Tab);
+  assert_equals(document.activeElement, btn);
+  await test_driver.send_keys(document.activeElement, Enter);
+  assert_equals(document.activeElement, btn, 'btn invoked menulist, but focus is still on btn.');
+  await test_driver.send_keys(document.activeElement, ArrowDown);
+  assert_equals(document.activeElement, A1, 'arrow down moves focus into menulist.');
+  await test_driver.send_keys(document.activeElement, ArrowLeft);
+  assert_equals(document.activeElement, A1, 'arrow left does not change current focused element.');
+  await test_driver.send_keys(document.activeElement, ArrowRight);
+  assert_equals(document.activeElement, A1, 'arrow right does not change current focused element.');
+  await test_driver.send_keys(document.activeElement, ArrowDown);
+  assert_equals(document.activeElement, A2, 'arrow down changes to next menuitem.');
+  await test_driver.send_keys(document.activeElement, ArrowUp);
+  assert_equals(document.activeElement, A1, 'arrow up changes to previous menuitem.');
+  await test_driver.send_keys(document.activeElement, ArrowUp);
+  assert_equals(document.activeElement, A1, 'arrow keys do not loop.');
+}, 'Should use arrow keys to move between menuitems in menulist.');
+
+promise_test(async (t) => {
+  await test_driver.click(B1);
+  assert_equals(document.activeElement, B1);
+  await test_driver.send_keys(document.activeElement, ArrowUp);
+  assert_equals(document.activeElement, B1, 'arrow up does not change current focused element.');
+  await test_driver.send_keys(document.activeElement, ArrowDown);
+  assert_equals(document.activeElement, B1, 'arrow down does not change current focused element.');
+  await test_driver.send_keys(document.activeElement, ArrowRight);
+  assert_equals(document.activeElement, B2, 'arrow right changes to next menuitem.');
+  await test_driver.send_keys(document.activeElement, ArrowLeft);
+  assert_equals(document.activeElement, B1, 'arrow left changes to previous menuitem.');
+  await test_driver.send_keys(document.activeElement, ArrowLeft);
+  assert_equals(document.activeElement, B1, 'arrow keys do not loop.');
+}, 'Should use arrow keys to move between menuitems in menubar.');
+
+</script>
diff --git a/html/semantics/menu/tentative/menu-elements-default-style-ref.html b/html/semantics/menu/tentative/menu-elements-default-style-ref.html
new file mode 100644
index 0000000..40e2ca8
--- /dev/null
+++ b/html/semantics/menu/tentative/menu-elements-default-style-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<style>
+  .menubar {
+    display: inline-block;
+  }
+
+  .menulist {
+    display: block;
+  }
+
+  .menuitem {
+    padding: 1em;
+  }
+
+  .menubar .menuitem {
+    display: inline-block;
+  }
+
+  .menulist .menuitem {
+    display: block;
+  }
+</style>
+
+<div class="menubar">
+  <div class="menuitem">Item A</div>
+  <div class="menuitem">Item B</div>
+  <div class="menuitem">Item C</div>
+</div>
+
+<br>
+
+<div class="menulist">
+  <div class="menuitem">Item A</div>
+  <div class="menuitem">Item B</div>
+  <div class="menuitem">Item C</div>
+</div>
diff --git a/html/semantics/menu/tentative/menu-elements-default-style.html b/html/semantics/menu/tentative/menu-elements-default-style.html
new file mode 100644
index 0000000..c409f03
--- /dev/null
+++ b/html/semantics/menu/tentative/menu-elements-default-style.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<link rel=author href=mailto:dom@chromium.org>
+<link rel=help href=https://open-ui.org/components/menu.explainer>
+<link rel="match" href="menu-elements-default-style-ref.html">
+
+<menubar>
+  <menuitem>Item A</menuitem>
+  <menuitem>Item B</menuitem>
+  <menuitem>Item C</menuitem>
+</menubar>
+
+<br>
+
+<menulist>
+  <menuitem>Item A</menuitem>
+  <menuitem>Item B</menuitem>
+  <menuitem>Item C</menuitem>
+</menulist>
+
+<script>
+const menulist = document.querySelector("menulist");
+menulist.showPopover();
+</script>
\ No newline at end of file
diff --git a/html/semantics/menu/tentative/menubar-invoke-menulist.html b/html/semantics/menu/tentative/menubar-invoke-menulist.html
new file mode 100644
index 0000000..35740f4
--- /dev/null
+++ b/html/semantics/menu/tentative/menubar-invoke-menulist.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=author href=mailto:dizhangg@chromium.org>
+<link rel=help href=https://open-ui.org/components/menu.explainer>
+
+<menubar>
+  <menuitem id="menubaritem">More commands</menuitem>
+  <menuitem>Command 2</menuitem>
+  <menuitem>Command 3</menuitem>
+</menubar>
+
+<menulist id="more">
+ <menuitem id="menulistitem" disabled>Command 1</menuitem>
+ <menuitem>Command 2</menuitem>
+</menulist>
+
+<script>
+const menubar = document.querySelector("menubar");
+const menubaritem = document.getElementById("menubaritem");
+const menulist = document.querySelector("menulist");
+const menulistitem = document.getElementById("menulistitem");
+
+test(() => {
+ assert_equals(menubar.constructor, HTMLMenuBarElement);
+ assert_equals(menubaritem.constructor, HTMLMenuItemElement);
+ assert_false(menubaritem.disabled);
+ menubaritem.disabled = true;
+ assert_true(menubaritem.disabled);
+
+ assert_equals(menulist.constructor, HTMLMenuListElement);
+ assert_equals(menulistitem.constructor, HTMLMenuItemElement);
+ assert_true(menulistitem.disabled);
+ menulistitem.disabled = false;
+ assert_false(menulistitem.disabled);
+}, "Menu elements are HTML elements.");
+
+test(() => {
+  // `defaultChecked`.
+  assert_equals(menubaritem.defaultChecked, undefined,
+      "menuitem does not have a defaultChecked attribute");
+
+  // `checked` content & IDL attribute behavior.
+  // By default, attribute missing/null, which translates to the false IDL
+  // boolean state.
+  assert_equals(menubaritem.getAttribute('checked'), null);
+  assert_false(menubaritem.checked);
+
+  // The IDL attribute reads from the same state that the content attribute
+  // writes to.
+  menubaritem.setAttribute("checked", "true");
+  assert_true(menubaritem.checked);
+
+  // But the IDL attribute does not reflect [1] the content attribute value,
+  // which means when it is updated, the content attribute does not change.
+  //
+  // [1]: https://html.spec.whatwg.org/C#reflect
+  menubaritem.checked = false;
+  assert_false(menubaritem.checked);
+  menubaritem.setAttribute("checked", "true");
+}, "menuitem checked attribute");
+
+test(() => {
+ menubaritem.setAttribute("command", "toggle-popover");
+ menubaritem.setAttribute("commandfor", "more");
+
+ menubaritem.disabled = true;
+ menubaritem.click();
+ assert_false(menulist.matches(':popover-open'),
+    'The menulist should not open because the menuitem is disabled.');
+
+ menubaritem.disabled = false;
+ menubaritem.click();
+ assert_true(menulist.matches(':popover-open'),
+    'The menulist should be able to open successfully.');
+
+ menulist.hidePopover();
+
+ menubaritem.setAttribute("command", "show-menu");
+ menubaritem.click();
+ assert_true(menulist.matches(':popover-open'));
+
+ menubaritem.setAttribute("command", "hide-menu");
+ menubaritem.click();
+ assert_false(menulist.matches(':popover-open'));
+
+ menulist.hidePopover();
+}, "Menuitem with valid command/commandfor can invoke menulist popover.");
+
+test(() => {
+ menubaritem.setAttribute("command", "toggle-menu");
+ menubaritem.setAttribute("commandfor", "dne");
+ menubaritem.click();
+ assert_false(menulist.matches(':popover-open'),
+    'The menulist should not open because the menuitem commandfor is invalid');
+
+ menubaritem.setAttribute("command", "toggle-menu-dne");
+ menubaritem.setAttribute("commandfor", "more");
+ menubaritem.click();
+ assert_false(menulist.matches(':popover-open'),
+    'The menulist should not open because the menuitem command is invalid');
+}, "Menuitem with invalid command/commandfor cannot invoke menulist popover.");
+</script>
diff --git a/html/semantics/menu/tentative/menulist-popover-attribute.html b/html/semantics/menu/tentative/menulist-popover-attribute.html
new file mode 100644
index 0000000..2ccd0a3
--- /dev/null
+++ b/html/semantics/menu/tentative/menulist-popover-attribute.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=author href=mailto:dizhangg@chromium.org>
+<link rel=help href=https://open-ui.org/components/menu.explainer>
+
+<menulist id="menu">
+ <menuitem>Command 1</menuitem>
+ <menuitem>Command 2</menuitem>
+</menulist>
+
+<script>
+test(() => {
+  assert_equals(menu.popover, null);
+  menu.showPopover();
+  assert_true(menu.matches(':popover-open'));
+  menu.hidePopover();
+
+  menu.popover = 'auto';
+  assert_equals(menu.popover, 'auto');
+  menu.showPopover();
+  assert_true(menu.matches(':popover-open'));
+  menu.hidePopover();
+
+  menu.popover = 'manual';
+  assert_equals(menu.popover, 'manual');
+  menu.showPopover();
+  assert_true(menu.matches(':popover-open'));
+  menu.hidePopover();
+
+  menu.popover = null;
+  assert_equals(menu.popover, null);
+  menu.showPopover();
+  assert_true(menu.matches(':popover-open'));
+  menu.hidePopover();
+}, "menulist is a popover by default.");
+</script>
\ No newline at end of file
diff --git a/shadow-dom/focus-navigation/menu/tentative/focus-menu-elements.html b/shadow-dom/focus-navigation/menu/tentative/focus-menu-elements.html
new file mode 100644
index 0000000..fe72c06
--- /dev/null
+++ b/shadow-dom/focus-navigation/menu/tentative/focus-menu-elements.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="author" title="Di Zhang" href="mailto:dizhangg@chromium.org">
+<link rel=help href=https://open-ui.org/components/menu.explainer>
+<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="/resources/testdriver-actions.js"></script>
+<script src='../../resources/shadow-dom.js'></script>
+<script src="../../resources/focus-utils.js"></script>
+
+<menubar>
+  <menuitem id="A" command="toggle-menu" commandfor="more">More commands</menuitem>
+  <menuitem id="B">Command B</menuitem>
+  <menuitem id="C">Command C</menuitem>
+</menubar>
+
+<menulist id="more">
+ <menuitem id="A1">Command A1</menuitem>
+ <menuitem id="A2">Command A2</menuitem>
+</menulist>
+
+<script>
+
+promise_test(async () => {
+  let elements = [
+    'A',
+    'B',
+    'C',
+  ];
+
+  await assert_focus_navigation_bidirectional(elements);
+}, 'Should focus on menuitems in menubar only.');
+
+</script>