Source code

Revision control

Copy as Markdown

Other Tools

function createTopLayerElement(t,topLayerType) {
let element, show, showing;
switch (topLayerType) {
case 'dialog':
element = document.createElement('dialog');
show = () => element.showModal();
showing = () => element.matches(':modal');
break;
case 'fullscreen':
element = document.createElement('div');
show = async (topmostElement) => {
// Be sure to add user activation to the topmost visible target:
await blessTopLayer(topmostElement);
await element.requestFullscreen();
};
showing = () => document.fullscreenElement === element;
break;
default:
assert_unreached('Invalid top layer type');
}
t.add_cleanup(() => element.remove());
return {element,show,showing};
}
function runTopLayerTests(testCases, testAnchorAttribute) {
testAnchorAttribute = testAnchorAttribute || false;
testCases.forEach(test => {
const description = test.firstChild.data.trim();
assert_equals(test.querySelectorAll('.target').length,1,'There should be exactly one target');
const target = test.querySelector('.target');
assert_true(!!target,'Invalid test case');
const popovers = Array.from(test.querySelectorAll('[popover]'));
assert_true(popovers.length > 0,'No popovers found');
['dialog','fullscreen'].forEach(topLayerType => {
promise_test(async t => {
const {element,show,showing} = createTopLayerElement(t,topLayerType);
target.appendChild(element);
// Show the popovers.
t.add_cleanup(() => popovers.forEach(popover => popover.hidePopover()));
popovers.forEach(popover => popover.showPopover());
popovers.forEach(popover => assert_true(popover.matches(':popover-open'),'All popovers should be open'));
// Activate the top layer element.
await show(popovers[popovers.length-1]);
assert_true(showing());
popovers.forEach(popover => assert_equals(popover.matches(':popover-open'),popover.dataset.stayOpen==='true','Incorrect behavior'));
// Add another popover within the top layer element and make sure entire stack stays open.
const newPopover = document.createElement('div');
t.add_cleanup(() => newPopover.remove());
newPopover.popover = popoverHintSupported() ? 'hint' : 'auto';
element.appendChild(newPopover);
popovers.forEach(popover => assert_equals(popover.matches(':popover-open'),popover.dataset.stayOpen==='true','Adding another popover shouldn\'t change anything'));
assert_true(showing(),'top layer element should still be top layer');
newPopover.showPopover();
assert_true(newPopover.matches(':popover-open'));
popovers.forEach(popover => assert_equals(popover.matches(':popover-open'),popover.dataset.stayOpen==='true','Showing the popover shouldn\'t change anything'));
assert_true(showing(),'top layer element should still be top layer');
},`${description} with ${topLayerType}`);
promise_test(async t => {
const {element,show,showing} = createTopLayerElement(t,topLayerType);
element.popover = popoverHintSupported() ? 'hint' : 'auto';
target.appendChild(element);
// Show the popovers.
t.add_cleanup(() => popovers.forEach(popover => popover.hidePopover()));
popovers.forEach(popover => popover.showPopover());
popovers.forEach(popover => assert_true(popover.matches(':popover-open'),'All popovers should be open'));
const targetWasOpenPopover = target.matches(':popover-open');
// Show the top layer element as a popover first.
element.showPopover();
assert_true(element.matches(':popover-open'),'element should be open as a popover');
assert_equals(target.matches(':popover-open'),targetWasOpenPopover,'target shouldn\'t change popover state');
try {
await show(element);
assert_unreached('It is an error to activate a top layer element that is already a showing popover');
} catch (e) {
// We expect an InvalidStateError for dialogs, and a TypeError for fullscreens.
// Anything else should fall through to the test harness.
if (e.name !== 'InvalidStateError' && e.name !== 'TypeError') {
throw e;
}
}
},`${description} with ${topLayerType}, top layer element *is* a popover`);
if (testAnchorAttribute) {
promise_test(async t => {
const {element,show,showing} = createTopLayerElement(t,topLayerType);
element.anchorElement = target;
document.body.appendChild(element);
// Show the popovers.
t.add_cleanup(() => popovers.forEach(popover => popover.hidePopover()));
popovers.forEach(popover => popover.showPopover());
popovers.forEach(popover => assert_true(popover.matches(':popover-open'),'All popovers should be open'));
// Activate the top layer element.
await show(popovers[popovers.length-1]);
assert_true(showing());
popovers.forEach(popover => assert_equals(popover.matches(':popover-open'),popover.dataset.stayOpen==='true','Incorrect behavior'));
},`${description} with ${topLayerType}, anchor attribute`);
}
});
});
}