Source code
Revision control
Copy as Markdown
Other Tools
<!DOCTYPE HTML>
<html>
<head>
<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="/wai-aria/scripts/aria-utils.js"></script>
</head>
<body>
<custom-element popovertarget="testPopover" id="testElement"></custom-element>
<custom-button popovertarget="testPopover" id="testButton"></custom-button>
<div id="testPopover" popover>
Test popover for custom element button behavior
</div>
<script>
class CustomButton extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals_ = this.attachInternals();
this.internals_.type = "button";
}
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(value) {
if (value) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
}
customElements.define('custom-button', CustomButton);
class CustomElement extends HTMLElement {
constructor() {
super();
this.internals_ = this.attachInternals();
}
}
customElements.define('custom-element', CustomElement);
function resetState() {
const testButton = document.getElementById("testButton");
const popover = document.getElementById("testPopover");
testButton.removeAttribute('popovertargetaction');
testButton.removeAttribute('disabled');
popover.hidePopover();
}
test(t => {
// Without type=button, popovertarget should not work.
document.getElementById("testElement").click();
assert_false(document.getElementById("testPopover").matches(':popover-open'), "The popover should not be shown when the custom element doesn't have type=button.");
}, "Autonomous custom element without ElementInternals.type=button does not support the popovertarget attribute.");
test(t => {
const popover = document.getElementById("testPopover");
const testButton = document.getElementById("testButton");
testButton.setAttribute('popovertargetaction', 'toggle');
t.add_cleanup(() => resetState());
// Initially closed, first click should open.
assert_false(popover.matches(':popover-open'), "Toggle popover should start closed");
testButton.click();
assert_true(popover.matches(':popover-open'), "Toggle popover should open after first click");
// Second click should close.
testButton.click();
assert_false(popover.matches(':popover-open'), "Toggle popover should close after second click");
// Third click should open again.
testButton.click();
assert_true(popover.matches(':popover-open'), "Toggle popover should open again after third click");
}, "Custom element with type=button and popovertargetaction='toggle' toggles popover.");
test(t => {
const popover = document.getElementById("testPopover");
const testButton = document.getElementById("testButton");
testButton.setAttribute('popovertargetaction', 'show');
t.add_cleanup(() => resetState());
// Initially closed.
assert_false(popover.matches(':popover-open'), "Show popover should start closed");
// First click should open.
testButton.click();
assert_true(popover.matches(':popover-open'), "Show popover should open after first click");
// Second click should not close (show action only opens).
testButton.click();
assert_true(popover.matches(':popover-open'), "Show popover should remain open after second click");
}, "Custom element with type=button and popovertargetaction='show' only opens popover.");
test(t => {
const popover = document.getElementById("testPopover");
const testButton = document.getElementById("testButton");
testButton.setAttribute('popovertargetaction', 'hide');
t.add_cleanup(() => resetState());
// Start with popover open.
popover.showPopover();
assert_true(popover.matches(':popover-open'), "Hide popover should start open");
// First click should close.
testButton.click();
assert_false(popover.matches(':popover-open'), "Hide popover should close after first click");
// Second click should not open (hide action only closes).
testButton.click();
assert_false(popover.matches(':popover-open'), "Hide popover should remain closed after second click");
}, "Custom element with type=button and popovertargetaction='hide' only closes popover.");
test(t => {
const popover = document.getElementById("testPopover");
const testButton = document.getElementById("testButton");
testButton.setAttribute('disabled', '');
popover.hidePopover();
t.add_cleanup(() => resetState());
// Disabled button should not open popover.
assert_true(testButton.disabled, "Button should be disabled");
assert_false(popover.matches(':popover-open'), "Popover should start closed");
testButton.click();
assert_false(popover.matches(':popover-open'), "Disabled button should not open popover");
// Enable the button and verify it works.
testButton.disabled = false;
assert_false(testButton.disabled, "Button should be enabled");
testButton.click();
assert_true(popover.matches(':popover-open'), "Enabled button should open popover");
// Disable again and verify clicking doesn't close it.
testButton.disabled = true;
testButton.click();
assert_true(popover.matches(':popover-open'), "Disabled button should not close popover");
}, "Custom element with type=button that is disabled does not support popovertarget.");
</script>
</body>
</html>