blob: 53ded3ed0eba3c4175fb5e0719e6ea3850b23a6d [file] [log] [blame]
<!DOCTYPE html>
<meta charset="utf-8">
<title>Interactions between top layer element types</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.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>
<body>
<script>
const types = Object.freeze({
popup: Symbol("Popup API"),
modalDialog: Symbol("Modal Dialog"),
fullscreen: Symbol("Fullscreen Element"),
});
const examples = [
{
type: types.popup,
closes: [types.popup],
createElement: () => Object.assign(document.createElement('div'), {popup: 'popup'}),
trigger: function() {this.element.showPopup()},
close: function() {this.element.hidePopup()},
isTopLayer: function() {return this.element.matches(':popup-open')},
},
{
type: types.modalDialog,
closes: [types.popup],
createElement: () => document.createElement('dialog'),
trigger: function() {this.element.showModal();this.showing=true;},
close: function() {this.element.close();this.showing=false;},
isTopLayer: function() {return !!(this.element.isConnected && this.showing);},
},
{
type: types.fullscreen,
closes: [types.popup, types.fullscreen],
createElement: () => document.createElement('div'),
trigger: async function(visibleElement) {assert_false(this.isTopLayer());await bless(visibleElement);await this.element.requestFullscreen();},
close: function() {assert_equals(this.element,document.fullscreenElement); document.exitFullscreen();},
isTopLayer: function() {return this.element.matches(':fullscreen');},
},
];
function createElement(ex) {
assert_true(!ex.element);
const element = ex.element = ex.createElement();
assert_true(!!element);
element.appendChild(document.createTextNode(`This is a ${ex.type.description}`));
document.body.appendChild(element);
assert_false(ex.isTopLayer(),'Element should start out not in the top layer');
return element;
}
function doneWithExample(ex) {
assert_true(!!ex.element);
if (ex.isTopLayer())
ex.close();
ex.element.remove();
ex.element = null;
}
async function bless(visibleElement) {
// The normal "bless" function doesn't work well when there are top layer
// elements blocking clicks. Additionally, since the normal test_driver.bless
// function just adds a button to the main document and clicks it, we can't
// call that in the presence of open popups, since that click will close them.
const button = document.createElement('button');
button.innerHTML = "Click me to activate";
visibleElement.appendChild(button);
let wait_click = new Promise(resolve => button.addEventListener("click", resolve, {once: true}));
await test_driver.click(button);
await wait_click;
button.remove();
}
// Test interactions between top layer elements
for(let i=0;i<examples.length;++i) {
for(let j=0;j<examples.length;++j) {
const example1 = Object.assign([],examples[i]);
const example2 = Object.assign([],examples[j]);
const shouldClose = example2.closes.includes(example1.type);
const desc = `A ${example2.type.description} should ${shouldClose ? "" : "*not*"} close a ${example1.type.description}`;
promise_test(async t => {
const element1 = createElement(example1);
const element2 = createElement(example2);
t.add_cleanup(() => {doneWithExample(example1);doneWithExample(example2);});
await example1.trigger(document.body); // Open the 1st top layer element
assert_true(example1.isTopLayer()); // Make sure it is top layer
await example2.trigger(element1); // Open the 2nd top layer element
assert_true(example2.isTopLayer()); // Make sure it is top layer
assert_equals(shouldClose,!example1.isTopLayer(),desc);
},desc);
}
}
</script>