behaves-like-button-with-popover.tentative.html (5935B)
1 <!DOCTYPE HTML> 2 <html> 3 4 <head> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/resources/testdriver.js"></script> 8 <script src="/resources/testdriver-vendor.js"></script> 9 <script src="/resources/testdriver-actions.js"></script> 10 <script src="/wai-aria/scripts/aria-utils.js"></script> 11 </head> 12 13 <body> 14 <custom-element popovertarget="testPopover" id="testElement"></custom-element> 15 <custom-button popovertarget="testPopover" id="testButton"></custom-button> 16 <div id="testPopover" popover> 17 Test popover for custom element button behavior 18 </div> 19 20 <script> 21 class CustomButton extends HTMLElement { 22 static formAssociated = true; 23 constructor() { 24 super(); 25 this.internals_ = this.attachInternals(); 26 this.internals_.type = "button"; 27 } 28 29 get disabled() { 30 return this.hasAttribute('disabled'); 31 } 32 33 set disabled(value) { 34 if (value) { 35 this.setAttribute('disabled', ''); 36 } else { 37 this.removeAttribute('disabled'); 38 } 39 } 40 } 41 customElements.define('custom-button', CustomButton); 42 43 class CustomElement extends HTMLElement { 44 constructor() { 45 super(); 46 this.internals_ = this.attachInternals(); 47 } 48 } 49 customElements.define('custom-element', CustomElement); 50 51 function resetState() { 52 const testButton = document.getElementById("testButton"); 53 const popover = document.getElementById("testPopover"); 54 testButton.removeAttribute('popovertargetaction'); 55 testButton.removeAttribute('disabled'); 56 popover.hidePopover(); 57 } 58 59 test(t => { 60 // Without type=button, popovertarget should not work. 61 document.getElementById("testElement").click(); 62 assert_false(document.getElementById("testPopover").matches(':popover-open'), "The popover should not be shown when the custom element doesn't have type=button."); 63 }, "Autonomous custom element without ElementInternals.type=button does not support the popovertarget attribute."); 64 65 test(t => { 66 const popover = document.getElementById("testPopover"); 67 const testButton = document.getElementById("testButton"); 68 testButton.setAttribute('popovertargetaction', 'toggle'); 69 t.add_cleanup(() => resetState()); 70 71 // Initially closed, first click should open. 72 assert_false(popover.matches(':popover-open'), "Toggle popover should start closed"); 73 testButton.click(); 74 assert_true(popover.matches(':popover-open'), "Toggle popover should open after first click"); 75 76 // Second click should close. 77 testButton.click(); 78 assert_false(popover.matches(':popover-open'), "Toggle popover should close after second click"); 79 80 // Third click should open again. 81 testButton.click(); 82 assert_true(popover.matches(':popover-open'), "Toggle popover should open again after third click"); 83 }, "Custom element with type=button and popovertargetaction='toggle' toggles popover."); 84 85 test(t => { 86 const popover = document.getElementById("testPopover"); 87 const testButton = document.getElementById("testButton"); 88 testButton.setAttribute('popovertargetaction', 'show'); 89 t.add_cleanup(() => resetState()); 90 91 // Initially closed. 92 assert_false(popover.matches(':popover-open'), "Show popover should start closed"); 93 94 // First click should open. 95 testButton.click(); 96 assert_true(popover.matches(':popover-open'), "Show popover should open after first click"); 97 98 // Second click should not close (show action only opens). 99 testButton.click(); 100 assert_true(popover.matches(':popover-open'), "Show popover should remain open after second click"); 101 }, "Custom element with type=button and popovertargetaction='show' only opens popover."); 102 103 test(t => { 104 const popover = document.getElementById("testPopover"); 105 const testButton = document.getElementById("testButton"); 106 testButton.setAttribute('popovertargetaction', 'hide'); 107 t.add_cleanup(() => resetState()); 108 109 // Start with popover open. 110 popover.showPopover(); 111 assert_true(popover.matches(':popover-open'), "Hide popover should start open"); 112 113 // First click should close. 114 testButton.click(); 115 assert_false(popover.matches(':popover-open'), "Hide popover should close after first click"); 116 117 // Second click should not open (hide action only closes). 118 testButton.click(); 119 assert_false(popover.matches(':popover-open'), "Hide popover should remain closed after second click"); 120 }, "Custom element with type=button and popovertargetaction='hide' only closes popover."); 121 122 test(t => { 123 const popover = document.getElementById("testPopover"); 124 const testButton = document.getElementById("testButton"); 125 testButton.setAttribute('disabled', ''); 126 popover.hidePopover(); 127 t.add_cleanup(() => resetState()); 128 129 // Disabled button should not open popover. 130 assert_true(testButton.disabled, "Button should be disabled"); 131 assert_false(popover.matches(':popover-open'), "Popover should start closed"); 132 133 testButton.click(); 134 assert_false(popover.matches(':popover-open'), "Disabled button should not open popover"); 135 136 // Enable the button and verify it works. 137 testButton.disabled = false; 138 assert_false(testButton.disabled, "Button should be enabled"); 139 140 testButton.click(); 141 assert_true(popover.matches(':popover-open'), "Enabled button should open popover"); 142 143 // Disable again and verify clicking doesn't close it. 144 testButton.disabled = true; 145 testButton.click(); 146 assert_true(popover.matches(':popover-open'), "Disabled button should not close popover"); 147 }, "Custom element with type=button that is disabled does not support popovertarget."); 148 </script> 149 </body> 150 151 </html>