diff --git a/testing/web-platform/tests/html/semantics/popups/popup-invoking-attribute.tentative.html b/testing/web-platform/tests/html/semantics/popups/popup-invoking-attribute.tentative.html
index 7108acc9ae6a8..49056f8b77ff9 100644
--- a/testing/web-platform/tests/html/semantics/popups/popup-invoking-attribute.tentative.html
+++ b/testing/web-platform/tests/html/semantics/popups/popup-invoking-attribute.tentative.html
@@ -3,22 +3,190 @@
Popup invoking attribute
+
-
-This is popup #1
-
-
+ return {expectedBehavior, expectedId};
+}
+const textLogic = (t,s,h) => {
+ // This mimics the expected logic for text field invokers, which can
+ // only be shown via the down arrow, and never hidden.
+ return {expectedBehavior: (t || s) ? "show" : "none", expectedId: t || s || 1};
+};
+const noActivationLogic = (t,s,h) => {
+ // This does not activate any popups.
+ return {expectedBehavior: "none", expectedId: 1};
+}
+function activateTextInputFn(arrowChoice) {
+ return async (el) => {
+ // Press the down arrow
+ let key;
+ switch (arrowChoice) {
+ case 'down': key = '\uE015'; break; // ArrowDown
+ case 'right': key = '\uE014'; break; // ArrowRight
+ default: assert_unreached('invalid choice');
+ }
+ await new test_driver.send_keys(el,key);
+ };
+}
+function makeElementWithType(element,type) {
+ return (test) => {
+ const el = Object.assign(document.createElement(element),{type});
+ document.body.appendChild(el);
+ test.add_cleanup(() => el.remove());
+ return el;
+ };
+}
+const supportedButtonTypes = ['button','reset','submit',''].map(type => {
+ return {
+ name: `