diff --git a/html/semantics/popups/popup-animation-corner-cases.tentative.html b/html/semantics/popups/popup-animation-corner-cases.tentative.html index 917f0d900d1502..c463139b3c64ec 100644 --- a/html/semantics/popups/popup-animation-corner-cases.tentative.html +++ b/html/semantics/popups/popup-animation-corner-cases.tentative.html @@ -45,7 +45,10 @@ const {popUp, descendent} = createPopUp(t,'animation'); assert_false(isElementVisible(popUp)); assert_equals(descendent.parentElement.parentElement,popUp); + assert_true(popUp.matches(':closed')); + assert_false(popUp.matches(':open')); popUp.showPopUp(); + assert_false(popUp.matches(':closed')); assert_true(popUp.matches(':open')); assert_true(isElementVisible(popUp)); assert_equals(popUp.getAnimations({subtree: true}).length,0); @@ -53,6 +56,7 @@ const animations = popUp.getAnimations({subtree: true}); assert_equals(animations.length,2,'There should be two animations running'); assert_false(popUp.matches(':open'),'popUp should not match :open as soon as hidden'); + assert_false(popUp.matches(':closed'),'popUp should not match :closed until animations complete'); assert_true(isElementVisible(popUp),'but animations should keep the popUp visible'); assert_true(isElementVisible(descendent),'The descendent should also be visible'); await waitForRender(); @@ -61,6 +65,7 @@ assert_true(isElementVisible(popUp),'PopUp should still be visible due to animation'); animations.forEach(animation => animation.finish()); // Force the animations to finish await waitForRender(); // Wait one frame + assert_true(popUp.matches(':closed'),'The pop up should now match :closed'); assert_false(popUp.matches(':open'),'The pop up still shouldn\'t match :open'); assert_false(isElementVisible(popUp),'The pop up should now be invisible'); assert_false(isElementVisible(descendent),'The descendent should also be invisible'); @@ -82,6 +87,7 @@ // Then hide the popUp. popUp.hidePopUp(); assert_false(popUp.matches(':open'),'pop up should not match :open as soon as hidden'); + assert_true(popUp.matches(':closed'),'pop up should match :closed immediately'); assert_equals(popUp.getAnimations({subtree: true}).length,2,'animations should still be running'); await waitForRender(); assert_equals(popUp.getAnimations({subtree: true}).length,2,'animations should still be running'); @@ -137,6 +143,27 @@ assert_false(isElementVisible(popUp),'Even if hide event is cancelled, the popup still closes'); },'hide event cannot be cancelled'); +promise_test(async (t) => { + const {popUp, descendent} = createPopUp(t,'animation'); + assert_false(isElementVisible(popUp)); + popUp.showPopUp(); + assert_false(popUp.matches(':closed')); + assert_true(popUp.matches(':open')); + assert_true(isElementVisible(popUp)); + assert_equals(popUp.getAnimations({subtree: true}).length,0); + popUp.popUp = 'manual'; + const animations = popUp.getAnimations({subtree: true}); + assert_equals(animations.length,2,'There should be two animations running'); + assert_false(popUp.matches(':open'),'popUp should not match :open as soon as hidden'); + assert_false(popUp.matches(':closed'),'popUp should not match :closed until animations complete'); + assert_true(isElementVisible(popUp),'but animations should keep the popUp visible'); + animations.forEach(animation => animation.finish()); // Force the animations to finish + await waitForRender(); // Wait one frame + assert_true(popUp.matches(':closed'),'The pop up should now match :closed'); + assert_false(popUp.matches(':open'),'The pop up still shouldn\'t match :open'); + assert_false(isElementVisible(popUp),'The pop up should now be invisible'); +},'Closing animations are triggered by changing the pop-up type'); + promise_test(async (t) => { const {popUp, descendent} = createPopUp(t,''); popUp.showPopUp(); diff --git a/html/semantics/popups/popup-attribute-basic.tentative.html b/html/semantics/popups/popup-attribute-basic.tentative.html index de8d4d5f897003..e5b49ec9b19430 100644 --- a/html/semantics/popups/popup-attribute-basic.tentative.html +++ b/html/semantics/popups/popup-attribute-basic.tentative.html @@ -47,9 +47,11 @@ if (isVisible) { assert_not_equals(window.getComputedStyle(popUp).display,'none'); assert_equals(popUp.matches(':open'),isPopUp,`${message}: Visible pop-ups should match :open`); + assert_false(popUp.matches(':closed'),`${message}: Visible pop-ups and *all* non-pop-ups should *not* match :closed`); } else { assert_equals(window.getComputedStyle(popUp).display,'none',`${message}: Non-showing pop-ups should have display:none`); assert_false(popUp.matches(':open'),`${message}: Non-showing pop-ups should *not* match :open`); + assert_true(popUp.matches(':closed'),`${message}: Non-showing pop-ups should match :closed`); } } function assertIsFunctionalPopUp(popUp) { @@ -89,7 +91,7 @@ }); // Then loop through all HTML5 elements that render a box by default: - let elementsThatDontRender = ['audio','base','br','datalist','dialog','embed','head','link','meta','noscript','param','rp','script','style','template','title','wbr']; + let elementsThatDontRender = ['audio','base','br','datalist','dialog','embed','head','link','meta','noscript','param','rp','script','slot','style','template','title','wbr']; const elements = HTML5_ELEMENTS.filter(el => !elementsThatDontRender.includes(el)); elements.forEach(tag => { test((t) => { @@ -98,7 +100,13 @@ document.body.appendChild(element); t.add_cleanup(() => element.remove()); assertIsFunctionalPopUp(element); - }, `A <${tag}> element should behave as a pop-up.`); + }, `A <${tag} popup> element should behave as a pop-up.`); + test((t) => { + const element = document.createElement(tag); + document.body.appendChild(element); + t.add_cleanup(() => element.remove()); + assertNotAPopUp(element); + }, `A <${tag}> element should *not* behave as a pop-up.`); }); function createPopUp(t) { @@ -318,6 +326,7 @@ assert_false(isElementVisible(popUp)); popUp.showPopUp(); assert_true(popUp.matches(':open')); + assert_false(popUp.matches(':closed')); assert_true(getComputedStyle(popUp).opacity < 0.1,'Animations should start on show'); assert_throws_dom("InvalidStateError",() => popUp.showPopUp(),'Calling showPopUp on a popup that is in the process of animating show should throw InvalidStateError'); await finishAnimations(popUp); @@ -325,10 +334,12 @@ assert_true(isElementVisible(popUp)); popUp.hidePopUp(); assert_false(popUp.matches(':open')); + assert_false(popUp.matches(':closed'),'Not :closed until animations finish'); assert_true(getComputedStyle(popUp).opacity > 0.9,'Animations should start on hide'); assert_throws_dom("InvalidStateError",() => popUp.hidePopUp(),'Calling hidePopUp on a popup that is in the process of animating hide should throw InvalidStateError'); popUp.showPopUp(); // But showPopUp should still be ok. popUp.hidePopUp(); // Clean up await finishAnimations(popUp); + assert_true(popUp.matches(':closed'),':closed should match once animations finish'); },'Exceptions are thrown even when show/hide are animated')