Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dialog.requestClose() in two ways #49223

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,132 @@
assert_false(dialog.open,'Without user activation, requestClose can\'t be cancelled');
},`requestClose requires user activation in order to be cancelable`);

async function setup(t,closedby) {
t.add_cleanup(() => {
dialog.close();
dialog.removeAttribute('closedby');
dialog.returnValue = '';
});
assert_false(dialog.hasAttribute('closedby'));
if (closedby) {
dialog.setAttribute('closedby',closedby);
}
// Be sure any pending close events get fired.
await new Promise(resolve => requestAnimationFrame(resolve));
return getSignal(t);
}

[false,true].forEach(modal => {
promise_test(async (t) => {
t.add_cleanup(() => dialog.close());
openDialog(modal);
dialog.requestClose();
assert_false(dialog.open);
},`${modal ? "Modal:" : "Non-modal:"} requestClose closes the dialog`);
[null,'any','closedrequest','none'].forEach(closedby => {
const testDescription = `for ${modal ? "modal" : "modeless"} dialog with closedby=${closedby}`;
promise_test(async (t) => {
await setup(t,closedby);
openDialog(modal);
if (dialog.closedBy != "none") {
dialog.requestClose();
assert_false(dialog.open);
} else {
assert_throws_dom('InvalidStateError',() => dialog.requestClose());
assert_true(dialog.open);
}
},`requestClose basic behavior ${testDescription}`);

promise_test(async (t) => {
const signal = await setup(t,closedby);
let events = [];
dialog.addEventListener('cancel',() => events.push('cancel'),{signal});
dialog.addEventListener('close',() => events.push('close'),{signal});
openDialog(modal);
assert_array_equals(events,[]);
if (dialog.closedBy != "none") {
dialog.requestClose();
assert_false(dialog.open);
assert_array_equals(events,['cancel'],'close is scheduled');
await new Promise(resolve => requestAnimationFrame(resolve));
assert_array_equals(events,['cancel','close']);
} else {
assert_throws_dom('InvalidStateError',() => dialog.requestClose());
}
},`requestClose fires both cancel and close ${testDescription}`);

promise_test(async (t) => {
t.add_cleanup(() => dialog.close());
const signal = getSignal(t);
let shouldPreventDefault = true;
dialog.addEventListener('cancel',(e) => {
if (shouldPreventDefault) {
e.preventDefault();
promise_test(async (t) => {
const signal = await setup(t,'none');
let events = [];
dialog.addEventListener('cancel',() => events.push('cancel'),{signal});
dialog.addEventListener('close',() => events.push('close'),{signal});
openDialog(modal);
dialog.setAttribute('closedby',closedby);
assert_array_equals(events,[]);
if (dialog.closedBy != "none") {
dialog.requestClose();
assert_false(dialog.open);
} else {
assert_throws_dom('InvalidStateError',() => dialog.requestClose());
}
},{signal});
openDialog(modal);
await clickOn(dialog); // User activation
dialog.requestClose();
assert_true(dialog.open,'cancel event was cancelled - dialog shouldn\'t close');
shouldPreventDefault = false;
await clickOn(dialog); // User activation
dialog.requestClose();
assert_false(dialog.open,'cancel event was not cancelled - dialog should now close');
},`${modal ? "Modal:" : "Non-modal:"} requestClose can be cancelled`);
},`changing closedby from 'none' to '${closedby}' for ${modal ? "modal" : "modeless"} dialog`);

promise_test(async (t) => {
const signal = await setup(t,closedby);
let events = [];
dialog.addEventListener('cancel',() => events.push('cancel'),{signal});
dialog.addEventListener('close',() => events.push('close'),{signal});
openDialog(modal);
dialog.removeAttribute('closedby');
assert_array_equals(events,[]);
if (dialog.closedBy != "none") {
dialog.requestClose();
assert_false(dialog.open);
} else {
assert_throws_dom('InvalidStateError',() => dialog.requestClose());
}
},`Removing closedby when closedby='${closedby}' for ${modal ? "modal" : "modeless"} dialog`);

if (dialog.closedBy != "none") {
promise_test(async (t) => {
const signal = await setup(t,closedby);
let shouldPreventDefault = true;
dialog.addEventListener('cancel',(e) => {
if (shouldPreventDefault) {
e.preventDefault();
}
},{signal});
openDialog(modal);
await clickOn(dialog); // User activation
dialog.requestClose();
assert_true(dialog.open,'cancel event was cancelled - dialog shouldn\'t close');
shouldPreventDefault = false;
await clickOn(dialog); // User activation
dialog.requestClose();
assert_false(dialog.open,'cancel event was not cancelled - dialog should now close');
},`requestClose can be cancelled ${testDescription}`);

promise_test(async (t) => {
await setup(t,closedby);
openDialog(modal);
assert_equals(dialog.returnValue,'','Return value starts out empty');
const returnValue = 'The return value';
dialog.requestClose(returnValue);
assert_false(dialog.open);
assert_equals(dialog.returnValue,returnValue,'Return value should be set');
dialog.show();
dialog.close();
assert_equals(dialog.returnValue,returnValue,'Return value should not be changed by close()');
dialog.show();
dialog.close('another');
assert_equals(dialog.returnValue,'another','Return value changes via close(value)');
},`requestClose(returnValue) passes along the return value ${testDescription}`);

promise_test(async (t) => {
await setup(t,closedby);
dialog.addEventListener('cancel',(e) => e.preventDefault(),{once:true});
openDialog(modal);
dialog.returnValue = 'foo';
assert_equals(dialog.returnValue,'foo');
dialog.requestClose('This should not get saved');
assert_true(dialog.open,'cancelled');
assert_equals(dialog.returnValue,'foo','Return value should not be changed');
},`requestClose(returnValue) doesn't change returnvalue when cancelled ${testDescription}`);
}
});
});
</script>