diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/fullscreen | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/fullscreen')
87 files changed, 3207 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fullscreen/META.yml b/testing/web-platform/tests/fullscreen/META.yml new file mode 100644 index 0000000000..fbdb76390c --- /dev/null +++ b/testing/web-platform/tests/fullscreen/META.yml @@ -0,0 +1,5 @@ +spec: https://fullscreen.spec.whatwg.org/ +suggested_reviewers: + - aliams + - foolip + - upsuper diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html new file mode 100644 index 0000000000..c96a56f352 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title> + Document#exitFullscreen() when the document is not the active document +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe allowfullscreen></iframe> +<script> + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + const stolenTypeError = iframe.contentWindow.TypeError; + const documentBeforeNav = iframe.contentDocument; + + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = "about:blank"; + }); + + await promise_rejects_js( + t, + stolenTypeError, + documentBeforeNav.documentElement.requestFullscreen(), + "Promise should be undefined after navigation" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html new file mode 100644 index 0000000000..893814dec3 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Document#exitFullscreen() for nested fullscreen inside an iframe</title> +<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="../trusted-click.js"></script> +<iframe allowfullscreen></iframe> +<script> + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.srcdoc = "<div id='outer'><div id='inner'></div></div>"; + }); + const iframeDoc = iframe.contentDocument; + const outer = iframeDoc.getElementById("outer"); + const inner = iframeDoc.getElementById("inner"); + + // First request fullscreen for the outer element. + await Promise.all([fullScreenChange(), trusted_request(outer)]); + assert_equals(document.fullscreenElement, iframe); + assert_equals(iframeDoc.fullscreenElement, outer); + + // Then request fullscreen for the inner element. + await Promise.all([fullScreenChange(), trusted_request(inner)]); + assert_equals(document.fullscreenElement, iframe); + assert_equals(iframeDoc.fullscreenElement, inner); + + // Now exit fullscreen for the iframe's content document. + await Promise.all([fullScreenChange(), iframeDoc.exitFullscreen()]); + assert_equals(document.fullscreenElement, null); + assert_equals(iframeDoc.fullscreenElement, null); + }, "Exit fullscreen for nested fullscreen inside an iframe"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html new file mode 100644 index 0000000000..695ae00322 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html @@ -0,0 +1,69 @@ +<!doctype html> +<title>Exiting fullscreen from a nested shadow root should work correctly.</title> +<link rel="author" title="Mozilla" href="https://mozilla.org"> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1652155"> +<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> +<div id="host"> + <button> + <!-- + This is gross, but testdriver doesn't let us click stuff in shadow + DOM, so here we are instead, using nested slots. + --> + fullscreen + </button> +</div> +<script> +promise_test(async function() { + let host = document.getElementById("host"); + host.attachShadow({ mode: "open" }).innerHTML = ` + <style> + #outer { width: 200px; height: 200px; background: blue } + </style> + <div id="outer"> + <slot></slot> + </div> + `; + + let outer = host.shadowRoot.getElementById("outer"); + outer.attachShadow({ mode: "open" }).innerHTML = ` + <style> + #inner { width: 100px; height: 100px; background: purple } + </style> + <div id="inner"></div> + <slot></slot> + `; + + let button = document.querySelector("button"); + + let inner = outer.shadowRoot.getElementById("inner"); + let finished = new Promise(resolve => { + button.addEventListener("click", async function() { + await outer.requestFullscreen(); + assert_equals(outer.getRootNode().fullscreenElement, outer); + assert_equals(document.fullscreenElement, host); + + button.addEventListener("click", async function() { + await inner.requestFullscreen(); + assert_equals(inner.getRootNode().fullscreenElement, inner); + assert_equals(document.fullscreenElement, host); + await document.exitFullscreen(); + assert_equals(inner.getRootNode().fullscreenElement, null); + assert_equals(outer.getRootNode().fullscreenElement, outer); + assert_equals(document.fullscreenElement, host); + resolve(); + }, { once: true }); + + requestAnimationFrame(() => requestAnimationFrame(() => { + test_driver.click(button); + })); + }, { once: true }); + }); + + test_driver.click(button); + await finished; +}, "Exiting fullscreen from a nested shadow root works correctly."); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html new file mode 100644 index 0000000000..37332b9b8f --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<title>Document#exitFullscreen() for nested fullscreen</title> +<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="../trusted-click.js"></script> +<div><div></div></div> +<script> + promise_test(async (t) => { + const outer = document.querySelector("div"); + const inner = outer.firstChild; + + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + + // First request fullscreen for the outer element. + await Promise.all([ + fullScreenChange(), + trusted_request(outer), + ]); + + assert_equals(document.fullscreenElement, outer); + + // Then request fullscreen for the inner element. + const p = trusted_request(inner); + + // Even though we are already in fullscreen, the change in + // document.fullscreenElement should not happen synchronously. + assert_equals(document.fullscreenElement, outer); + await Promise.all([ + fullScreenChange(), + p, + ]); + assert_equals(document.fullscreenElement, inner); + + // Now exit fullscreen. + const exitP = document.exitFullscreen(); + // Even though we don't need to exit fullscreen, the change in + // document.fullscreenElement should not happen synchronously. + assert_equals(document.fullscreenElement, inner); + await Promise.all([ + exitP, + fullScreenChange(), + ]); + assert_equals(document.fullscreenElement, outer); + }, "Exit fullscreen for nested fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html new file mode 100644 index 0000000000..43e01743b9 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<title>Document#exitFullscreen() timing</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + const div = document.querySelector("div"); + await trusted_request(div); + + await Promise.all([ + new Promise((r) => (document.onfullscreenchange = r)), + document.exitFullscreen(), + ]); + + // If fullscreenchange is an animation frame event, then animation frame + // callbacks should be run after it is fired, before the timer callback. + // The resize event should fire before the fullscreenchange event. + const events = []; + const callback = t.step_func((event) => { + // fullscreenElement should have changed before either event is fired. + assert_equals( + document.fullscreenElement, + null, + `fullscreenElement in ${event.type} event` + ); + events.push(event.type); + if (event.type == "fullscreenchange") { + step_timeout(t.unreached_func("timer callback")); + requestAnimationFrame( + t.step_func_done(() => { + assert_array_equals( + events, + ["resize", "fullscreenchange"], + "event order" + ); + }) + ); + } + }); + document.onfullscreenchange = window.onresize = callback; + }, "Timing of fullscreenchange and resize events"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html new file mode 100644 index 0000000000..aa8538cce4 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<title>Document#exitFullscreen() called twice</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + const once = { once: true }; + const div = document.querySelector("div"); + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + + await Promise.all([ + fullScreenChange(), + trusted_request(div), + ]); + + // We are now in fullscreen. + assert_equals(document.fullscreenElement, div); + + // Exit fullscreen twice. + const firstPromise = document.exitFullscreen(); + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement after first exitFullscreen()" + ); + + const secondPromise = document.exitFullscreen(); + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement after second exitFullscreen()" + ); + const eventChange = new Promise((resolve) => { + document.addEventListener("fullscreenchange", resolve, once); + document.addEventListener( + "fullscreenchange", + t.unreached_func("second event fired"), + once + ); + }); + + await Promise.all([ + fullScreenChange, + firstPromise, + secondPromise, + eventChange, + ]); + assert_equals(document.fullscreenElement, null); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html new file mode 100644 index 0000000000..666950ff55 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Document#exitFullscreen()</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<body></body> +<script> + promise_test(async function (t) { + const div = document.querySelector("div"); + // enter fullscreen + await trusted_request(div); + + // Exit fullscreen + const [event] = await Promise.all([ + fullScreenChange(), + document.exitFullscreen(), + ]); + + // Check event from exiting fullscreen + assert_equals(event.target, div, "event.target"); + assert_true(event.bubbles, "event.bubbles"); + assert_false(event.cancelable, "event.cancelable"); + assert_true(event.composed, "event.composed"); + }, "Checks that the fullscreenchange event is fired when exiting fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html new file mode 100644 index 0000000000..8b3a16a2a8 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<title>Document#fullscreenElement</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async function (t) { + const div = document.querySelector("div"); + + await trusted_click(); + + assert_equals( + document.fullscreenElement, + null, + "fullscreenElement before requestFullscreen()" + ); + + const fsPromise = div.requestFullscreen(); + assert_equals( + document.fullscreenElement, + null, + "fullscreenElement after requestFullscreen()" + ); + await fsPromise; + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement before exitFullscreen()" + ); + const exitPromise = document.exitFullscreen(); + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement after exitFullscreen()" + ); + await Promise.all([fullScreenChange(), exitPromise]); + + assert_equals( + document.fullscreenElement, + null, + "fullscreenElement after exiting fullscreen" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html new file mode 100644 index 0000000000..360982c4a5 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title> + Document#fullscreenEnabled when the document is not the active document +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe allowfullscreen></iframe> +<script> + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + const documentBeforeNav = iframe.contentDocument; + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = "/common/blank.html"; + }); + assert_false(documentBeforeNav.fullscreenEnabled) + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html new file mode 100644 index 0000000000..bcfc98bbca --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Document#fullscreenEnabled</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe src="resources/report-fullscreen-enabled.html" name="same-origin-default"></iframe> +<iframe src="resources/report-fullscreen-enabled.html" allowfullscreen name="same-origin-allow"></iframe> +<iframe src="http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/report-fullscreen-enabled.html" name="cross-origin-default"></iframe> +<iframe src="http://{{hosts[][]}}:{{ports[http][1]}}/fullscreen/api/resources/report-fullscreen-enabled.html" allowfullscreen name="cross-origin-allow"></iframe> +<script> +var expectations = { + "same-origin-default": true, + "same-origin-allow": true, + "cross-origin-default": false, + "cross-origin-allow": true +}; + +var tests = {}; +for (var name in expectations) { + tests[name] = async_test( 'Fullscreen enabled test: ' + name); +} + +// When a message is received from a child frame, ensure that the report +// matches the expectations. +window.addEventListener('message', e => { + if (e.data.report && e.data.report.api == "fullscreen") { + if (e.data.report.frame in expectations) { + tests[e.data.report.frame].step(() => { + assert_equals(e.data.report.enabled, expectations[e.data.report.frame], + e.data.report.frame + " frame fullscreenEnabled"); + }); + delete expectations[e.data.report.frame]; + tests[e.data.report.frame].done(); + } + } +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html new file mode 100644 index 0000000000..687a4ff1e4 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<title> + Document#fullscreenEnabled removing allowfullscreen after load and then + navigating +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe></iframe> +<script> + function requestStatus(iframe) { + iframe.contentWindow.postMessage( + "What is document.fullscreenEnabled?", + "*" + ); + return new Promise((resolve) => { + window.addEventListener("message", function listener(e) { + window.removeEventListener("message", listener); + resolve(event.data); + }); + }); + } + + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + iframe.allowFullscreen = true; + assert_true(iframe.allowFullscreen, "allowFullscreen is false"); + assert_true( + iframe.hasAttribute("allowfullscreen"), + "allowFullscreen attribute is present" + ); + await new Promise((resolve) => { + iframe.onload = resolve; + const path = location.pathname.substring( + 0, + location.pathname.lastIndexOf("/") + 1 + ); + iframe.src = `http://{{hosts[][]}}:{{ports[http][0]}}${path}resources/echo-fullscreenEnabled.html`; + }); + + assert_true( + await requestStatus(iframe), + "document.fullscreenEnabled in the iframe, before navigation" + ); + + iframe.allowFullscreen = false; + assert_false(iframe.allowFullscreen, "allowFullscreen is false"); + assert_false( + iframe.hasAttribute("allowfullscreen"), + "allowFullscreen attribute is not present" + ); + + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.contentWindow.location.href = iframe.src + "?2"; + }); + + assert_false( + await requestStatus(iframe), + "document.fullscreenEnabled in the iframe, after navigation" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html new file mode 100644 index 0000000000..49d91c8501 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<title>Document#fullscreenEnabled setting allowfullscreen after document creation, before response</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +// Set allowfullscreen attribute in a timeout after <iframe> has been inserted to the document. +// The iframe's response is delayed so it happens after the attribute is set. + +async_test((t) => { + const iframe = document.createElement('iframe'); + // no allowfullscreen attribute + + const path = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1); + iframe.src = "http://{{hosts[][]}}:{{ports[http][0]}}" + path + "resources/echo-fullscreenEnabled.html?pipe=trickle(d1)"; + iframe.onload = t.step_func(() => { + iframe.contentWindow.postMessage('What is document.fullscreenEnabled?', '*'); + }); + + window.onmessage = t.step_func_done((e) => { + assert_false(e.data, 'document.fullscreenEnabled in the iframe'); + }); + + document.body.appendChild(iframe); + + t.step_timeout(() => { + iframe.allowFullscreen = true; + }, 10); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html new file mode 100644 index 0000000000..4894fa0663 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Document#fullscreenEnabled setting allowfullscreen after load and then navigating</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +async_test((t) => { + const iframe = document.createElement('iframe'); + // no allowfullscreen attribute + + let i = 0; + + const path = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1); + iframe.src = "http://{{hosts[][]}}:{{ports[http][0]}}" + path + "resources/echo-fullscreenEnabled.html"; + iframe.onload = t.step_func(() => { + if (i === 0) { + iframe.allowFullscreen = true; + } + iframe.contentWindow.postMessage('What is document.fullscreenEnabled?', '*'); + }); + + window.onmessage = t.step_func((e) => { + i++; + if (i === 1) { + assert_false(e.data, 'document.fullscreenEnabled in the iframe, before navigation'); + + // Navigate the iframe. This will fire a second 'load' event on the iframe. + iframe.contentWindow.location.href = iframe.src + '?2'; + } else { + assert_true(e.data, 'document.fullscreenEnabled in the iframe, after navigation'); + t.done(); + } + }); + + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html new file mode 100644 index 0000000000..40430d7bbf --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Document#fullscreenEnabled</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe></iframe> +<script> +test(function() +{ + assert_true(document.fullscreenEnabled, "top-level document"); + const iframe = document.querySelector("iframe"); + assert_true(iframe.contentDocument.fullscreenEnabled, "same-origin iframe"); +}); + +// The cross-origin iframe case is tested in +// /html/semantics/embedded-content/the-iframe-element/iframe-allowfullscreen.html +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html b/testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html new file mode 100644 index 0000000000..10503c6ccb --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<title>Document#onfullscreenchange</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + const div = document.querySelector("div"); + assert_equals( + document.onfullscreenchange, + null, + "initial onfullscreenchange" + ); + const [, event] = await Promise.all([ + trusted_request(div), + new Promise((r) => + document.addEventListener("fullscreenchange", r) + ), + ]); + assert_true(event instanceof Event); + assert_equals(event.target, div); + }, "Checks that the fullscreenchange event is fired when entering fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html b/testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html new file mode 100644 index 0000000000..ac92a9c24b --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title>Document#onfullscreenerror</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + assert_equals( + document.onfullscreenerror, + null, + "initial onfullscreenerror" + ); + const [, event] = await Promise.all([ + promise_rejects_js( + t, + TypeError, + document.documentElement.requestFullscreen() + ), + new Promise((r) => document.addEventListener("fullscreenerror", r)), + ]); + assert_equals(event.target, document.documentElement); + assert_true(event instanceof Event); + }, "Checks that the fullscreenerror event is fired when entering fullscreen fails"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-allowed.html b/testing/web-platform/tests/fullscreen/api/element-ready-allowed.html new file mode 100644 index 0000000000..79890fa82f --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-allowed.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<title>Element ready check with enabled flag not set</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<iframe></iframe> +<script> + promise_test(async function (t) { + const iframe = document.querySelector("iframe"); + await new Promise((r) => { + iframe.onload = r; + iframe.src = "about:blank"; + }); + document.onfullscreenchange = t.unreached_func( + "document fullscreenchange event" + ); + document.onfullscreenerror = t.unreached_func( + "document fullscreenerror event" + ); + iframe.contentDocument.onfullscreenchange = t.unreached_func( + "iframe fullscreenchange event" + ); + assert_false(iframe.allowFullscreen, "fullscreen enabled flag"); + assert_true( + iframe.contentDocument.fullscreenEnabled, + "fullscreen enabled flag" + ); + return trusted_request(iframe.contentDocument.body, document.body); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html new file mode 100644 index 0000000000..9c93ed006b --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<title>Element ready check with allowfullscreen attribute</title> +<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="../trusted-click.js"></script> +<iframe name="cross-origin-allowed" allowfullscreen></iframe> +<script> + promise_test(async (t) => { + // Trigger the child frame to report as soon as its content is loaded. + const iframe = document.querySelector("iframe"); + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = + "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/attempt-fullscreen.html"; + }); + + // Activate the child frame. + await test_driver.click(iframe); + + // When a message is received from a child frame, ensure that the report + // matches the expectations. + const messagePromise = promiseMessage(iframe); + const data = await messagePromise; + assert_true( + data.report.result, + `${data.report.frame} frame did enter fullscreen` + ); + }, "Element ready check with allowfullscreen attribute"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html new file mode 100644 index 0000000000..8d55aea563 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>Element ready check for containing iframe</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<iframe allowfullscreen></iframe> +<iframe allowfullscreen></iframe> +<script> + // wait for load event to avoid https://bugzil.la/1493878 + window.onload = function () { + promise_test(async function (t) { + const [iframe1, iframe2] = document.getElementsByTagName("iframe"); + + iframe2.contentDocument.onfullscreenerror = t.unreached_func( + "fullscreenerror event" + ); + + await Promise.all([ + trusted_request( + iframe1.contentDocument.body, + iframe1.contentDocument.body + ), + fullScreenChange(), + ]); + + assert_equals(document.fullscreenElement, iframe1); + + await Promise.all([ + trusted_request( + iframe2.contentDocument.body, + iframe1.contentDocument.body + ), + fullScreenChange(iframe2.contentDocument), + ]); + }, "Element ready check for containing iframe"); + }; +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html new file mode 100644 index 0000000000..6394c13ee3 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>Element ready check for sibling of fullscreen element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="a"></div> +<div id="b"></div> +<script> + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func( + "second fullscreenchange event" + ); + const a = document.getElementById("a"); + const b = document.getElementById("b"); + await Promise.all([trusted_request(a), fullScreenChange()]); + + assert_equals(document.fullscreenElement, a, "fullscreen element is a"); + + await Promise.all([trusted_request(b, a), fullScreenChange()]); + assert_equals(document.fullscreenElement, b, "fullscreen element is b"); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html new file mode 100644 index 0000000000..77aad41e7d --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<title>Element ready check for child of a fullscreen iframe</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<iframe><!-- script inserts div here --></iframe> +<script> + // Verify that an iframe can itself go fullscreen, and that this doesn't + // influence the iframe ancestor test of the element ready check. + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + const iframe = document.querySelector("iframe"); + await Promise.all([trusted_request(iframe), fullScreenChange()]); + + assert_equals(document.fullscreenElement, iframe, "fullscreen element"); + + // This adds the div to the iframe element itself, not to the iframe's + // contentDocument. It's done here because the HTML parser treats the + // content of iframe as a text node. + var div = document.createElement("div"); + iframe.appendChild(div); + + await Promise.all([ + trusted_request(div, iframe.contentDocument.body), + fullScreenChange(), + ]); + assert_equals(document.fullscreenElement, div); + }, "Element ready check for child of a fullscreen iframe"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html new file mode 100644 index 0000000000..9b9d06ad75 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<title>Element ready check for child of iframe</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<iframe><!-- script inserts child here --></iframe> +<script> + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + const div = document.createElement("div"); + document.querySelector("iframe").appendChild(div); + + await Promise.all([ + trusted_request(div, document.body), + fullScreenChange(), + ]); + + assert_equals(document.fullscreenElement, div); + }, "Element ready check for child of iframe"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html new file mode 100644 index 0000000000..a59906ba9f --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<title>Element ready check with no allowfullscreen attribute</title> +<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="../trusted-click.js"></script> +<body> + <iframe name="cross-origin-default"></iframe> +</body> + +<script> + // Allow the time bomb to be triggered. + setup({ allow_uncaught_exception: true }); + + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) return document.exitFullscreen(); + }); + const iframe = document.querySelector("iframe"); + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = + "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/attempt-fullscreen.html"; + }); + // Trigger the child frame to report as soon as its content is loaded. + await trusted_click(); + const timeBomb = new Promise((resolve, reject) => { + t.step_timeout(() => { + const error = new Error("Timed out waiting for message"); + reject(error); + }, 5000); + }); + const data = await Promise.race([promiseMessage(iframe), timeBomb]); + // When a message is received from a child frame, ensure that the report + // matches the expectations. + assert_false( + data.report.result, + `${data.report.frame} frame entered fullscreen, but allowfullscreen was not set` + ); + }, "Cross-origin element ready check with no allowfullscreen or allow attribute"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html new file mode 100644 index 0000000000..210ccc2ace --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<title>Element ready check for element not in a document</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async function (t) { + const div = document.createElement("div"); + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + await Promise.all([ + promise_rejects_js( + t, + TypeError, + trusted_request(div, document.body) + ), + new Promise((resolve) => { + document.onfullscreenerror = resolve; + }), + ]); + }, "Element ready check for element not in a document"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html new file mode 100644 index 0000000000..bac8631059 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() when the document is not the active document +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe allowfullscreen></iframe> +<script> + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + const typeErrorConstructor = iframe.contentWindow.TypeError; + const documentBeforeNav = iframe.contentDocument; + + documentBeforeNav.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + documentBeforeNav.onfullscreenerror = t.unreached_func( + "fullscreenerror event" + ); + + await new Promise((r) => { + iframe.src = "/common/blank.html"; + iframe.onload = r; + }); + + await promise_rejects_js( + t, + typeErrorConstructor, + documentBeforeNav.documentElement.requestFullscreen() + ); + + // Per spec the fullscreenerror event should be fired at the next animation + // frame, but at least Gecko and WebKit will instead effectively do "queue a + // task to fire ...". Use both rAF and setTimeout to fail even if the timing + // of the (unexpected) event isn't as expected. + await new Promise((resolve) => { + requestAnimationFrame(() => { + t.step_timeout(resolve); + }); + }); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html new file mode 100644 index 0000000000..4278382770 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() after error</title> +<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> +<div id="log"></div> +<script> +promise_test(async t => { + await new Promise(r => window.onload = r); + + const element1 = document.createElement("div"); + document.body.appendChild(element1); + + await test_driver.bless("request full screen"); + let promise = element1.requestFullscreen() + await new Promise(r => t.step_timeout(r, 0)) + document.body.removeChild(element1); + try { + await promise; + assert_unreached("requestFullscreen shouldn't be successful"); + } catch (e) { + } + try { + await document.exitFullscreen(); + } catch (e) { + } + + const element2 = document.createElement("div"); + document.body.appendChild(element2); + + await test_driver.bless("request full screen"); + try { + await element2.requestFullscreen(); + } catch (e) { + assert_unreached("requestFullscreen shouldn't throw an error - " + e.message); + } + await document.exitFullscreen(); +}, "requestFullscreen works even if previous requestFullscreen causes an error"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html new file mode 100644 index 0000000000..f0bf5f6bac --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html @@ -0,0 +1,97 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() and Document#exitFullscreen() in iframe +</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<iframe allowfullscreen></iframe> +<script> + const iframe = document.querySelector("iframe"); + let iframeDoc; + let iframeBody; + + promise_setup(async () => { + const iframe = document.querySelector("iframe"); + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = "about:blank"; + }); + iframeDoc = iframe.contentDocument; + iframeBody = iframeDoc.body; + }); + /** + * + * @param {Document} doc + * @param {HTMLElement} value + * @returns {Promise<Event>} + */ + function makeChangeListener(doc) { + return new Promise((resolve) => { + doc.addEventListener("fullscreenchange", resolve, { once: true }); + }); + } + + // Both when entering and exiting, the fullscreenchange event is fired first + // on the outer document and then on the iframe's document. This is because + // the events are fired in animation frame tasks, which run in "frame tree" + // order. + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func( + "document fullscreenerror event" + ); + iframeDoc.onfullscreenerror = t.unreached_func( + "iframe fullscreenerror event" + ); + const outerPromise = makeChangeListener(document); + const innerPromise = makeChangeListener(iframeDoc); + const request = trusted_request(iframeBody, iframeBody); + + const winningEvent = await Promise.race([outerPromise, innerPromise]); + assert_equals(winningEvent.target, iframe); + + await Promise.allSettled([outerPromise, innerPromise, request]); + + assert_equals( + document.fullscreenElement, + iframe, + "outer fullscreenElement" + ); + + assert_equals( + iframeDoc.fullscreenElement, + iframeBody, + "inner fullscreenElement" + ); + }, "Checks that the fullscreenchange events fire in right order when entering fullscreen"); + + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func( + "document fullscreenerror event" + ); + iframeDoc.onfullscreenerror = t.unreached_func( + "iframe fullscreenerror event" + ); + const outerPromise = makeChangeListener(document); + const innerPromise = makeChangeListener(iframeDoc); + const exitPromise = iframeDoc.exitFullscreen(); + + const winningEvent = await Promise.race([outerPromise, innerPromise]); + assert_equals(winningEvent.target, iframe); + + await Promise.allSettled([outerPromise, innerPromise, exitPromise]); + assert_equals( + document.fullscreenElement, + null, + "outer fullscreenElement" + ); + assert_equals( + iframeDoc.fullscreenElement, + null, + "inner fullscreenElement" + ); + }, "Checks that the fullscreenchange events fire in right order when exiting fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html new file mode 100644 index 0000000000..f758835012 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() followed by moving the element into an iframe +</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="target"></div> +<iframe allowfullscreen></iframe> +<script> + // rfsPromise will be uncaught + setup({ allow_uncaught_exception: true }); + + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + await new Promise((r) => { + iframe.onload = r; + iframe.src = "about:blank"; + }); + const target = document.getElementById("target"); + const iframeDoc = iframe.contentDocument; + + iframeDoc.onfullscreenchange = t.unreached_func( + "fullscreenchange event in iframe" + ); + iframeDoc.onfullscreenerror = t.unreached_func( + "fullscreenerror event in iframe" + ); + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + + const errorPromise = new Promise( + (resolve) => (document.onfullscreenerror = resolve) + ); + await trusted_click(document.body); + const rfsPromise = target.requestFullscreen(); + iframeDoc.body.appendChild(target); + const event = await errorPromise; + assert_equals( + iframeDoc.fullscreenElement, + null, + "inner fullscreen element" + ); + assert_equals( + document.fullscreenElement, + null, + "outer fullscreen element" + ); + assert_equals(event.target, document, "event target"); + await promise_rejects_js( + t, + TypeError, + rfsPromise, + "requestFullscreen promise" + ); + }, "Element#requestFullscreen() followed by moving the element into an iframe"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html new file mode 100644 index 0000000000..f031461ce5 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() followed by moving the element within the + document +</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="target"></div> +<div id="moveto"></div> +<script> + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + const target = document.getElementById("target"); + const moveTo = document.getElementById("moveto"); + await trusted_click(document.body); + const p = target.requestFullscreen(); + moveTo.appendChild(target); + await Promise.all([p, fullScreenChange()]); + assert_equals(document.fullscreenElement, target); + assert_equals(target.parentNode, moveTo); + }, "Element#requestFullscreen() followed by moving the element within the document"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html new file mode 100644 index 0000000000..991799a48d --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() in iframe followed by removing the iframe +</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<iframe allowfullscreen></iframe> +<script> + promise_test(async (t) => { + const iframe = document.querySelector("iframe"); + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = "about:blank"; + }); + + const iframeDocument = iframe.contentDocument; + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + iframeDocument.onfullscreenchange = t.unreached_func( + "iframe fullscreenchange event" + ); + iframeDocument.onfullscreenerror = t.unreached_func( + "iframe fullscreenerror event" + ); + await trusted_click(document.body); + const p = iframeDocument.body.requestFullscreen(); + const typeErrorConstructor = iframe.contentWindow.TypeError; + iframe.remove(); + // Prevent the tests from hanging if the promise never rejects. + const errorPromise = new Promise((_, reject) => + t.step_timeout(() => { + assert_unreached("Promise didn't reject."); + reject(new Error("Promise didn't reject.")); + }, 1000) + ); + await Promise.race([ + promise_rejects_js(t, typeErrorConstructor, p), + errorPromise, + ]); + assert_equals(document.fullscreenElement, null); + assert_equals(iframeDocument.fullscreenElement, null); + }, "requestFullscreen() in iframe followed by removing the iframe"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html new file mode 100644 index 0000000000..436a61b6e1 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() followed by removing the element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="target"></div> +<script> + promise_test(async (t) => { + const target = document.getElementById("target"); + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + const errorEventPromise = new Promise( + (resolve) => (document.onfullscreenerror = resolve) + ); + await trusted_click(document.body); + const p = target.requestFullscreen(); + target.remove(); + Promise.all([promise_rejects_js(t, TypeError, p), errorEventPromise]); + }, "requestFullscreen() followed by removing the element"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html new file mode 100644 index 0000000000..cc4806711d --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() consumes user activation</title> +<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> +<div id="log"></div> +<script> +promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) return document.exitFullscreen(); + }); + const div = document.querySelector("div"); + + await test_driver.bless("fullscreen"); + assert_true(navigator.userActivation.isActive, "Activation must be active"); + // Request fullscreen twice in a row. The first request should consume the + // user activation and succeed, and the second request should fail because + // of the user activation requirement. + const p1 = div.requestFullscreen(); + assert_false(navigator.userActivation.isActive, "Transient activation is consumed"); + const p2 = promise_rejects_js(t, TypeError, div.requestFullscreen()); + await Promise.all([p1, p2]); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html new file mode 100644 index 0000000000..5f3a397bbc --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html @@ -0,0 +1,143 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() works properly with a tree of cross-origin iframes +</title> +<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> + function waitFor(action, frameName) { + return new Promise((resolve) => { + window.addEventListener("message", function listener(e) { + if (e.data.action === action && e.data.name === frameName) { + window.removeEventListener("message", listener); + resolve(event.data); + } + }); + }); + } + + function compare_report(report, expectedEvents) { + assert_equals( + report.events.length, + expectedEvents.length, + `Expected report for iframe "${report.frame}" to have ${expectedEvents.length} events: [${expectedEvents}]` + ); + report.events.forEach((value, i) => { + assert_equals( + value, + expectedEvents[i], + "Event type matches in order expected" + ); + }); + + report.events.length + ? assert_false( + report.fullscreenElementIsNull, + "Event fired, fullscreenElement is set" + ) + : assert_true( + report.fullscreenElementIsNull, + "No event fired, fullscreenElement is null" + ); + } + + const iframes = [ + { + name: "A", + src: "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?a", + allow_fullscreen: true, + expectedEvents: ["fullscreenchange"], + }, + { + name: "B", + src: "http://{{hosts[][]}}:{{ports[http][1]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?b", + allow_fullscreen: true, + expectedEvents: ["fullscreenchange"], + }, + { + name: "C", + src: "http://{{hosts[alt][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?c", + allow_fullscreen: true, + expectedEvents: ["fullscreenchange"], + }, + { + name: "D", + src: "http://{{hosts[alt][]}}:{{ports[http][1]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?d", + allow_fullscreen: true, + expectedEvents: ["fullscreenchange"], + }, + { + name: "E", + src: "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?e", + allow_fullscreen: true, + expectedEvents: [], + }, + ]; + + promise_setup(async () => { + // Add the first iframe. + const iframeDetails = iframes[0]; + const child_frame = document.createElement("iframe"); + child_frame.allow = iframeDetails.allow_fullscreen ? "fullscreen" : ""; + child_frame.name = iframeDetails.name; + child_frame.style.width = "100%"; + child_frame.style.height = "100%"; + child_frame.src = iframeDetails.src; + await new Promise((resolve) => { + child_frame.onload = resolve; + document.body.appendChild(child_frame); + }); + + // Create the nested iframes. + for (let i = 1; i < iframes.length; i++) { + const parentName = iframes[i - 1].name; + const details = iframes[i]; + child_frame.contentWindow.postMessage( + { action: "addIframe", iframe: details, name: parentName }, + "*" + ); + await waitFor("load", details.name); + } + }); + + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + document.onfullscreenerror = t.unreached_func( + "fullscreenerror event fired" + ); + const fsChangeFiredPromise = new Promise((resolve) => { + document.onfullscreenchange = resolve; + }); + + const child_frame = document.querySelector("iframe[name=A]"); + child_frame.contentWindow.postMessage( + { + action: "requestFullscreen", + name: "D", + }, + "*" + ); + + await waitFor("requestFullscreen", "D"); + + for (const frame of iframes.slice(1)) { + const data = { + action: "requestReport", + name: frame.name, + }; + child_frame.contentWindow.postMessage(data, "*"); + const { report } = await waitFor("report", frame.name); + compare_report(report, frame.expectedEvents); + } + await fsChangeFiredPromise; + }, "Element#requestFullscreen() works properly with a tree of cross-origin iframes"); + </script> +</body> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html new file mode 100644 index 0000000000..ee5e21306a --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() for dialog element</title> +<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> +<div id="log"></div> +<dialog></dialog> +<script> + promise_test(async (t) => { + const dialog = document.querySelector("dialog"); + assert_true(dialog instanceof HTMLDialogElement); + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + const errorEventPromise = new Promise( + (resolve) => (document.onfullscreenerror = resolve) + ); + Promise.all([ + promise_rejects_js(t, TypeError, dialog.requestFullscreen()), + errorEventPromise, + ]); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html new file mode 100644 index 0000000000..dffa8dbc90 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() for an element in null namespace</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + const supportedNS = [ + { ns: "http://www.w3.org/1999/xhtml", elemName: "div" }, + { ns: "http://www.w3.org/2000/svg", elemName: "svg" }, + { ns: "http://www.w3.org/1998/Math/MathML", elemName: "math" }, + ]; + + const unsupportedNS = [null, "https://unknown.namespace", ""]; + + for (const ns of unsupportedNS) { + promise_test(async (t) => { + const element = document.createElementNS(ns, "element"); + document.body.appendChild(element); + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + await promise_rejects_js(t, TypeError, trusted_request(element)); + }, `requestFullscreen() fails for an element in ${ns} namespace`); + } + + for (const { ns, elemName } of supportedNS) { + promise_test(async (t) => { + const element = document.createElementNS(ns, elemName); + document.body.appendChild(element); + await Promise.all([trusted_request(element), fullScreenChange()]); + await document.exitFullscreen(); + }, `requestFullscreen() succeed for an element in ${ns} namespace`); + } +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html new file mode 100644 index 0000000000..9bed70d695 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() for non-top element in fullscreen element stack +</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="first"> + <div id="last"></div> +</div> +<script> + promise_test(async (t) => { + const first = document.getElementById("first"); + const last = document.getElementById("last"); + + await Promise.all([trusted_request(first), fullScreenChange()]); + assert_equals(document.fullscreenElement, first); + + await Promise.all([trusted_request(last), fullScreenChange()]); + assert_equals(document.fullscreenElement, last); + + await Promise.all([trusted_request(first, last), fullScreenChange()]); + assert_equals(document.fullscreenElement, first); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html new file mode 100644 index 0000000000..e52895ad7e --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() when not allowed to request fullscreen +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + const div = document.querySelector("div"); + const errorEventPromise = new Promise( + (resolve) => (document.onfullscreenerror = resolve) + ); + const [, event] = await Promise.all([ + promise_rejects_js(t, TypeError, div.requestFullscreen()), + errorEventPromise, + ]); + assert_equals(event.type, "fullscreenerror"); + assert_equals(event.target, div, "event.target"); + assert_true(event.bubbles, "event.bubbles"); + assert_false(event.cancelable, "event.cancelable"); + assert_true(event.composed, "event.composed"); + }, "requestFullscreen() when not allowed to request fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html new file mode 100644 index 0000000000..c11f54f7b5 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen({ navigationUI }) support</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body></body> +<script> + // Tests for https://github.com/whatwg/fullscreen/pull/129. Because there are + // no normative requirements on what navigationUI should do, just test for + // basic support. (One could also check that the three allowed enum valid are + // supported and no others, but that would overlap with UA-specific tests.) + promise_test(async (t) => { + const invalidDict = { + get navigationUI() { + return "invalid-value"; + }, + }; + await promise_rejects_js( + t, + TypeError, + document.body.requestFullscreen(invalidDict) + ); + await promise_rejects_js( + t, + TypeError, + document.body.requestFullscreen({ navigationUI: "other-invalid-value" }) + ); + }, "requestFullscreen() with invalid navigationUI values"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.https.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.https.html new file mode 100644 index 0000000000..871c917dcc --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.https.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen({ screen }) tentative support</title> +<link rel="help" href="https://w3c.github.io/window-management/" /> +<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="../trusted-click.js"></script> +<body></body> +<script> + promise_test(async (t) => { + await test_driver.set_permission( + { name: "window-management" }, + "granted" + ); + + let screenGetterInvoked = false; + const options = { + get screen() { + screenGetterInvoked = true; + return undefined; + }, + }; + + await trusted_click(document.body); + await document.body.requestFullscreen(options); + assert_true(screenGetterInvoked); + }, "fullscreenOptions.screen getter is invoked on requestFullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html new file mode 100644 index 0000000000..a2b04dd173 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() on the current fullscreen element</title> +<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> +<div id="log"></div> +<script> +promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) return document.exitFullscreen(); + }); + + // Use the body element as the fullscreen element, because the second + // test_driver.bless() call needs to insert a button inside of it, which + // can't be clicked if another element is already fullscreen. + const target = document.body; + + // First enter fullscreen. + await test_driver.bless("fullscreen", () => target.requestFullscreen()); + assert_equals(document.fullscreenElement, target, "fullscreen element after first request"); + + // Now request fullscreen again, which should be a no-op. + await test_driver.bless("fullscreen", () => target.requestFullscreen()); + assert_equals(document.fullscreenElement, target, "fullscreen element after second request"); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html new file mode 100644 index 0000000000..8569c4df79 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() on the current fullscreen element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="target"></div> +<script> + promise_test(async (t) => { + const target = document.getElementById("target"); + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + + await Promise.all([ + fullScreenChange(), + trusted_request(target), + ]); + + assert_equals(document.fullscreenElement, target); + + // The next requestFullscreen() should fire no events due to "If element is + // doc's fullscreen element, terminate these subsubsteps." + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + + await trusted_click(target); + await target.requestFullscreen(); + assert_equals(document.fullscreenElement, target); + // Wait until after the next animation frame. + await new Promise((r) => requestAnimationFrame(r)); + }, "Element#requestFullscreen() on the current fullscreen element"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-screen-size.https.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-screen-size.https.html new file mode 100644 index 0000000000..1c2bc9e3d1 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-screen-size.https.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() does not affect Screen sizes +</title> +<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="../trusted-click.js"></script> +<body></body> +<script> + promise_test(async (t) => { + const screenWidth = window.screen.width; + const screenHeight = window.screen.height; + + if ('onchange' in window.screen) { + window.screen.onchange = () => { + assert_equals(window.screen.width, screenWidth); + assert_equals(window.screen.height, screenHeight); + } + t.add_cleanup(() => { window.screen.onchange = null; }); + } + + // Await a test_driver or manual click, fullscreen promise, and change. + await Promise.all([trusted_request(), fullScreenChange()]); + t.add_cleanup(() => { document.exitFullscreen(); }); + assert_not_equals(document.fullscreenElement, null); + + // Ensure the screen size is unchanged during fullscreen. + assert_equals(window.screen.width, screenWidth); + assert_equals(window.screen.height, screenHeight); + }, "Screen size is unchanged during element fullscreen"); + + promise_test(async (t) => { + const screenWidth = window.screen.width; + const screenHeight = window.screen.height; + + if ('onchange' in window.screen) { + window.screen.onchange = () => { + assert_equals(window.screen.width, screenWidth); + assert_equals(window.screen.height, screenHeight); + } + t.add_cleanup(() => { window.screen.onchange = null; }); + } + + // Await a test_driver or manual click to start tab content capture. + await trusted_click(); + const stream = await navigator.mediaDevices.getDisplayMedia( + {video:{displaySurface:"browser"}, selfBrowserSurface:"include"}); + const capabilities = stream.getVideoTracks()[0].getCapabilities(); + assert_equals(capabilities.displaySurface, "browser"); + t.add_cleanup(() => { stream.getTracks().forEach(t => t.stop()) }); + + // Await a test_driver or manual click, fullscreen promise, and change. + await Promise.all([trusted_request(), fullScreenChange()]); + t.add_cleanup(() => { document.exitFullscreen(); }); + assert_not_equals(document.fullscreenElement, null); + + // Ensure the screen size is unchanged during tab-capture fullscreen. + assert_equals(window.screen.width, screenWidth); + assert_equals(window.screen.height, screenHeight); + }, "Screen size is unchanged during tab-capture element fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html new file mode 100644 index 0000000000..44adfa6898 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() for SVG rect element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<svg> + <rect + width="300" + height="300" + style="fill: rgb(0, 255, 153)" + /> +</svg> +<script> + promise_test(async (t) => { + const rect = document.querySelector("rect"); + assert_true(rect instanceof SVGRectElement); + document.onfullscreenchange = t.unreached_func( + "fullscreenchange event" + ); + await trusted_click(document.body); + await Promise.all([ + promise_rejects_js(t, TypeError, rect.requestFullscreen()), + new Promise((resolve) => { + document.onfullscreenerror = resolve; + }), + ]); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html new file mode 100644 index 0000000000..e579f6e7d7 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() for SVG svg element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<svg></svg> +<script> + promise_test(async (t) => { + const svg = document.querySelector("svg"); + assert_true(svg instanceof SVGSVGElement); + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + await Promise.all([ + fullScreenChange(), + trusted_request(svg), + ]); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html new file mode 100644 index 0000000000..b7986575ff --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() timing</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> +promise_test(async t => { + const div = document.querySelector('div'); + + // If fullscreenchange is an animation frame event, then animation frame + // callbacks should be run after it is fired, before the timer callback. + // The resize event should fire before the fullscreenchange event. + const events = []; + const callback = t.step_func(event => { + // fullscreenElement should have changed before either event is fired. + assert_equals(document.fullscreenElement, div, `fullscreenElement in {event.type} event`); + events.push(event.type); + if (event.type == 'fullscreenchange') { + step_timeout(t.unreached_func('timer callback')); + requestAnimationFrame(t.step_func_done(() => { + assert_array_equals(events, ['resize', 'fullscreenchange'], 'event order'); + })); + } + }); + document.onfullscreenchange = window.onresize = callback; + await trusted_request(div); +}, 'Timing of fullscreenchange and resize events'); + +async_test(t => { + // Gecko throttles requestAnimationFrame before the first paint, so + // wrap the test to work around that. + requestAnimationFrame(t.step_func(() => { + var promise = document.createElement('a').requestFullscreen(); + var promise_executed = false; + promise.catch(()=>{promise_executed = true; }); + // If fullscreenerror is an animation frame event, then animation frame + // callbacks should be run after it is fired, before the timer callback. + document.onfullscreenerror = t.step_func(() => { + assert_true(promise_executed, "promise executed"); + step_timeout(t.unreached_func('timer callback')); + requestAnimationFrame(t.step_func_done()); + }); + })); +}, 'Timing of fullscreenerror event'); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html new file mode 100644 index 0000000000..59211856ab --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title> + Element#requestFullscreen() for top element in fullscreen element stack +</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="top"></div> +<script> + promise_test(async function (t) { + const top = document.getElementById("top"); + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + + await Promise.all([ + trusted_request(top), + new Promise((r) => + document.addEventListener("fullscreenchange", r) + ), + ]); + assert_equals(document.fullscreenElement, top); + await trusted_click(top); + await top.requestFullscreen(); + // A fullscreenerror event would be fired after an async section + // and an animation frame task, so wait until after that. + await new Promise((resolve) => { + t.step_timeout(() => { + requestAnimationFrame(resolve); + }); + }); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html new file mode 100644 index 0000000000..db53aec544 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() twice</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + const div = document.querySelector("div"); + await trusted_click(document.body); + const p = div.requestFullscreen(); + assert_equals( + document.fullscreenElement, + null, + "fullscreenElement after first requestFullscreen()" + ); + const rejectedPromises = [ + promise_rejects_js(t, TypeError, div.requestFullscreen()), + promise_rejects_js(t, TypeError, div.requestFullscreen()), + ]; + await Promise.all([p, fullScreenChange()]); + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement after entering fullscreen" + ); + // Ensure that there's are not more changes fullscreenchange event. + document.onfullscreenchange = t.unreached_func( + "second fullscreenchange event" + ); + await Promise.all(rejectedPromises); + await new Promise((r) => requestAnimationFrame(r)); + }, "requestFullscreen() multiple times after going fullscreen"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html new file mode 100644 index 0000000000..54419ea8fd --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen() on two elements in the same document</title> +<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="../trusted-click.js"></script> +<body> + <div id="a"></div> + <div id="b"></div> +</body> +<script> + promise_test(async (t) => { + document.onfullscreenerror = t.unreached_func("fullscreenerror event"); + + // Request fullscreen on both elements, but in reverse tree order. + const a = document.getElementById("a"); + const b = document.getElementById("b"); + + // Expect two fullscreenchange events, with document.fullscreenElement + // changing in the same order as the requests. + await trusted_click(b); + await Promise.all([b.requestFullscreen(), fullScreenChange()]); + assert_equals(document.fullscreenElement, b); + + await trusted_click(b); + await Promise.all([a.requestFullscreen(), fullScreenChange()]); + assert_equals(document.fullscreenElement, a); + }, "Element#requestFullscreen() on two elements in the same document"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html new file mode 100644 index 0000000000..fd9f249551 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Element#requestFullscreen()</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async function (t) { + const div = document.querySelector("div"); + await Promise.all([fullScreenChange(), trusted_request(div)]); + assert_equals(event.target, div, "event.target"); + assert_true(event.bubbles, "event.bubbles"); + assert_false(event.cancelable, "event.cancelable"); + assert_true(event.composed, "event.composed"); + await document.exitFullscreen(); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html b/testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html new file mode 100644 index 0000000000..fc6f232747 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html @@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html class="reftest-wait"> + <title> + Test that display:contents on fullscreen elements acts like + display:block + </title> + <meta charset="utf-8" /> + <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="../trusted-click.js"></script> + <link rel="author" href="mailto:masonf@chromium.org" /> + <link + rel="help" + href="https://fullscreen.spec.whatwg.org/#new-stacking-layer" + /> + <div id="target"></div> + <style> + #target { + display: contents; + background-color: green; + } + #target::backdrop { + display: contents; + } + </style> + + <script> + promise_test(async (t) => { + const target = document.querySelector("#target"); + await test_driver.bless("fullscreen"); + await target.requestFullscreen(); + await new Promise((resolve) => requestAnimationFrame(resolve)); + assert_equals(document.fullscreenElement, target); + assert_equals( + getComputedStyle(target).display, + "block", + "fullscreen element should have display:block" + ); + assert_equals( + getComputedStyle(target, "::backdrop").display, + "block", + "fullscreen element's ::backdrop should have display:block" + ); + await document.exitFullscreen(); + new Promise((resolve) => requestAnimationFrame(resolve)); + assert_equals(document.fullscreenElement, null); + assert_equals( + getComputedStyle(target).display, + "contents", + "fullscreen element should have display:contents after exiting fullscreen" + ); + }); + </script> +</html> diff --git a/testing/web-platform/tests/fullscreen/api/fullscreen-reordering.html b/testing/web-platform/tests/fullscreen/api/fullscreen-reordering.html new file mode 100644 index 0000000000..1a286c32c7 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/fullscreen-reordering.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<title>Re-requesting fullscreen doesn't fail but doesn't change order</title> +<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="../../html/semantics/popovers/resources/popover-utils.js"></script> + +<div class="elements"> + <div id="A">Element A</div> + <div id="B">Element B</div> +</div> + +<style> + .elements>div { + width:200px; + height:200px; + } + #A { background: blue; } + #B { background: green; } +</style> + +<script> +promise_test(async (t) => { + t.add_cleanup(async () => { + while (document.fullscreenElement) + await document.exitFullscreen(); + }); + document.onfullscreenerror = () => assert_unreached('fullscreenerror should not happen'); + const A = document.getElementById('A'); + const B = document.getElementById('B'); + assert_true(!isTopLayer(A) && !isTopLayer(B)); + await blessTopLayer(document.body); + await A.requestFullscreen(); + assert_equals(document.fullscreenElement,A,'first A request'); + assert_true(isTopLayer(A),'A top layer'); + await blessTopLayer(A); + try { + await B.requestFullscreen(); + } catch (error) { + assert_unreached('The second call to requestFullscreen rejected - it should be possible to put siblings into fullscreen together'); + } + assert_equals(document.fullscreenElement,B,'B request'); + assert_true(isTopLayer(B),'B top layer'); + assert_true(isTopLayer(A),'A still top layer'); + await blessTopLayer(B); + await A.requestFullscreen(); + assert_true(isTopLayer(A),'A is still top layer'); + assert_true(isTopLayer(B),'B is still top layer'); + assert_equals(document.fullscreenElement,A,'A is moved back to the top of the top layer stack'); + assert_equals(document.elementFromPoint(10,10),A,'A should be topmost'); + + await document.exitFullscreen(); + assert_equals(document.fullscreenElement,B,'B goes back to being the fullscreen element'); + assert_true(isTopLayer(B),'B is still top layer'); + assert_false(isTopLayer(A),'A is no longer top layer'); + await document.exitFullscreen(); + assert_equals(document.fullscreenElement,null,'Both closed'); + assert_false(isTopLayer(A),'A is no longer top layer'); + assert_false(isTopLayer(B),'B is no longer top layer'); +}, 'Requesting fullscreen on A, then B, then A'); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/historical.html b/testing/web-platform/tests/fullscreen/api/historical.html new file mode 100644 index 0000000000..8b3e3c03e9 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/historical.html @@ -0,0 +1,38 @@ +<!doctype html> +<title>Historical Fullscreen features</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +[ + "onwebkitfullscreenchange", + "onwebkitfullscreenerror", + "webkitCurrentFullScreenElement", + "webkitFullscreenElement", + "webkitFullscreenEnabled", + "webkitIsFullScreen", + "webkitRequestFullScreen", + "webkitRequestFullscreen", + "webkitDisplayingFullscreen", + "webkitEnterFullScreen", + "webkitEnterFullscreen", + "webkitExitFullScreen", + "webkitExitFullscreen", + "webkitSupportsFullscreen", +].forEach(function(member) { + ["webkit", "moz", "ms"].forEach(function(prefix) { + var alias = member.replace("webkit", prefix); + var clarifyTestName = (alias.indexOf('FullScreen') != -1 ? ' (uppercase S)' : ''); + + test(function() { + assert_false(alias in document.createElement('video')); + }, '<video> member must not be supported: ' + alias + clarifyTestName); + + test(function() { + assert_false(alias in document); + }, 'Document member must not be supported: ' + alias + clarifyTestName); + + // Some of the combinations tested here have never been supported, but + // it is convenient to just test all names on both <video> and document. + }); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/promises-reject.html b/testing/web-platform/tests/fullscreen/api/promises-reject.html new file mode 100644 index 0000000000..4385b1646d --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/promises-reject.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Promises#reject</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + promise_test(async (t) => { + const e = document.createElement("span"); + await promise_rejects_js( + t, + TypeError, + e.requestFullscreen(), + "Rejects if the element is not connected" + ); + await promise_rejects_js( + t, + TypeError, + document.exitFullscreen(), + "Not in fullscreen" + ); + }, "Rejects if the element is not connected"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/promises-resolve.html b/testing/web-platform/tests/fullscreen/api/promises-resolve.html new file mode 100644 index 0000000000..5b8a090628 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/promises-resolve.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<title>Promises#resolve</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<script> + promise_test(async function (t) { + const div = document.querySelector("div"); + await trusted_request(div, document.body); + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement before exitFullscreen()" + ); + const p = document.exitFullscreen(); + assert_equals( + document.fullscreenElement, + div, + "fullscreenElement after exitFullscreen()" + ); + await p; + assert_equals( + document.fullscreenElement, + null, + "fullscreenElement after exiting fullscreen" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html b/testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html new file mode 100644 index 0000000000..98cca04516 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>IFrame Fullscreen API success reporter</title> +<body></body> +<script> + window.addEventListener("message", async (e) => { + switch (e.data.action) { + case "report": + await sendReport(); + break; + default: + parent.postMessage( + { + report: { + api: "fullscreen", + result: `Unknown action ${e.data.action}`, + frame: window.name, + }, + }, + "*" + ); + } + }); + + async function sendReport() { + let didSucceed = true; + let error; + let errorMessage; + try { + await document.body.requestFullscreen(); + } catch (e) { + didSucceed = false; + error = e.name; + errorMessage = e.message; + } finally { + const data = { + report: { + api: "fullscreen", + result: didSucceed, + frame: window.name, + error, + errorMessage, + }, + }; + parent.postMessage(data, "*"); + } + } +</script> diff --git a/testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html b/testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html new file mode 100644 index 0000000000..ad5edf7986 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html @@ -0,0 +1,11 @@ +<!doctype html> +<script> +window.onmessage = (e) => { + if (e.data === 'What is document.fullscreenEnabled?') { + e.source.postMessage(document.fullscreenEnabled, '*'); + } else { + e.source.postMessage('Incorrect message', '*'); + } +} +</script> +<p>This page echos document.fullscreenEnabled.</p> diff --git a/testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html b/testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html new file mode 100644 index 0000000000..d242a3b3e6 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html @@ -0,0 +1,86 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Recursive IFrame Fullscreen API success reporter</title> +<body> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <script src="../../trusted-click.js"></script> + <script> + let child_frame = null; + const events = []; + + document.onfullscreenchange = () => { + events.push("fullscreenchange"); + }; + + document.onfullscreenerror = () => { + events.push("fullscreenerror"); + }; + + function send_report() { + window.top.postMessage( + { + name: window.name, + action: "report", + report: { + api: "fullscreen", + frame: window.name, + fullscreenElementIsNull: document.fullscreenElement === null, + events, + }, + }, + "*" + ); + } + + async function create_child_frame({ src, name, allow_fullscreen }) { + child_frame = document.createElement("iframe"); + child_frame.allow = allow_fullscreen ? "fullscreen" : ""; + child_frame.name = name; + child_frame.style.width = "100%"; + child_frame.style.height = "100%"; + document.body.appendChild(child_frame); + await new Promise((resolve) => { + child_frame.addEventListener("load", resolve, { once: true }); + child_frame.src = src; + }); + window.top.postMessage({ action: "load", name }, "*"); + } + + async function go_fullscreen() { + await trusted_click(document.body); + let error; + try { + await document.body.requestFullscreen(); + } catch (err) { + error = err.name; + } finally { + window.top.postMessage( + { action: "requestFullscreen", name: window.name, error }, + "*" + ); + } + } + + window.addEventListener("message", async (e) => { + // Massage is not for us, try to pass it on... + if (e.data.name !== window.name) { + child_frame?.contentWindow.postMessage(e.data, "*"); + return; + } + switch (e.data.action) { + case "requestReport": + send_report(); + break; + case "requestFullscreen": + await go_fullscreen(); + break; + case "addIframe": + await create_child_frame(e.data.iframe); + break; + default: + window.top.postMessage(e.data, "*"); + } + }); + </script> +</body> diff --git a/testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html b/testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html new file mode 100644 index 0000000000..ee8d4cfab7 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>IFrame fullscreenEnabled attribute reporter</title> +<body> +<script> +parent.postMessage({"report": { + "api": "fullscreen", + "enabled": document.fullscreenEnabled, + "frame": window.name +}}, "*"); +</script> diff --git a/testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html b/testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html new file mode 100644 index 0000000000..5e605f00aa --- /dev/null +++ b/testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html @@ -0,0 +1,47 @@ +<!doctype html> +<html> +<head> + <title>shadowRoot.fullscreenElement works correctly</title> + <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> + <link rel="help" href="https://fullscreen.spec.whatwg.org/#dom-document-fullscreenelement"> +</head> +<div id="host"> + <button onclick="document.exitFullscreen()" id="exitButton">Exit fullscreen</button> +</div> +<button id="requestButton">Go fullscreen</button> + +<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> +promise_test(async function() { + let host = document.getElementById("host"); + host.attachShadow({ mode: "open" }).innerHTML = ` + <style> + #outer { width: 200px; height: 200px; background: blue } + </style> + <div id="outer"> + <slot></slot> + </div> + `; + let outer = host.shadowRoot.querySelector("#outer"); + await new Promise((resolve) => { + addEventListener("fullscreenchange", resolve, { once: true }); + requestButton.addEventListener("click", () => outer.requestFullscreen()); + test_driver.click(requestButton); + }); + + assert_equals(outer.getRootNode().fullscreenElement, outer, "Correct shadowRoot.fullscreenElement after entering"); + assert_equals(document.fullscreenElement, host, "Correct document.fullscreenElement after entering"); + + await new Promise((resolve) => { + addEventListener("fullscreenchange", resolve, { once: true }); + test_driver.click(exitButton); + }); + + assert_equals(outer.getRootNode().fullscreenElement, null, "Correct shadowRoot.fullscreenElement after exiting"); + assert_equals(document.fullscreenElement, null, "Correct document.fullscreenElement after exiting"); +}, "shadowRoot.fullscreenElement works correctly"); +</script> +</html> diff --git a/testing/web-platform/tests/fullscreen/crashtests/backdrop-list-item.html b/testing/web-platform/tests/fullscreen/crashtests/backdrop-list-item.html new file mode 100644 index 0000000000..c5f58263ff --- /dev/null +++ b/testing/web-platform/tests/fullscreen/crashtests/backdrop-list-item.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" /> +<link rel="help" href="https://crbug.com/1371331"> +<style> +dialog::backdrop { + display: list-item; +} +</style> +<dialog></dialog> +<script> +document.querySelector("dialog").showModal(); +</script> diff --git a/testing/web-platform/tests/fullscreen/crashtests/chrome-1312699.html b/testing/web-platform/tests/fullscreen/crashtests/chrome-1312699.html new file mode 100644 index 0000000000..c783b0d9cc --- /dev/null +++ b/testing/web-platform/tests/fullscreen/crashtests/chrome-1312699.html @@ -0,0 +1,21 @@ +<!doctype html> +<html class="reftest-wait"> +<link rel="help" href="https://crbug.com/1312699"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<video></video> +<script> + async function crash() { + let video = document.querySelector("video"); + await video.requestFullscreen(); + video.width = null; + document.documentElement.classList.remove("reftest-wait"); + } + document.addEventListener("click", () => crash(), false); + + requestAnimationFrame(() => requestAnimationFrame(() => { + test_driver.click(document.body); + })); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/fullscreen/crashtests/content-visibility-crash.html b/testing/web-platform/tests/fullscreen/crashtests/content-visibility-crash.html new file mode 100644 index 0000000000..63111d03e3 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/crashtests/content-visibility-crash.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html class=test-wait> +<link rel=author href="mailto:m.cooolie@gmail.com"> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1338135"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<body> +<script> +async function crash() { + const col = document.createElement("col"); + document.body.appendChild(col); + + let fullscreenPromise = null; + await test_driver.bless('open fullscreen', () => { + fullscreenPromise = col.requestFullscreen({navigationUI: 'hide'}); + }); + await fullscreenPromise; + + const a = document.createElement("a"); + document.body.appendChild(a); + + document.body.style.all = 'unset'; + document.body.style.contentVisibility = 'hidden'; + + a.offsetParent; + + document.documentElement.classList.remove('test-wait'); +} +crash(); +</script> diff --git a/testing/web-platform/tests/fullscreen/idlharness.window.js b/testing/web-platform/tests/fullscreen/idlharness.window.js new file mode 100644 index 0000000000..ddcc59c403 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/idlharness.window.js @@ -0,0 +1,16 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +'use strict'; + +idl_test( + ['fullscreen'], + ['dom', 'html'], + idl_array => { + idl_array.add_objects({ + Document: ['new Document'], + Element: ['document.createElementNS(null, "test")'], + }); + } +); diff --git a/testing/web-platform/tests/fullscreen/model/move-fullscreen-element.html b/testing/web-platform/tests/fullscreen/model/move-fullscreen-element.html new file mode 100644 index 0000000000..27f4c5dd82 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/move-fullscreen-element.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<title>Moving the fullscreen element should not leave the fullscreen flag</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<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="../trusted-click.js"></script> + +<div id="fullscreen-element">Fullscreen element</div> + +<div id="new-parent"></div> + +<script> + promise_test(async () => { + const fullscreenElement = document.getElementById("fullscreen-element"); + await trusted_request(fullscreenElement); + assert_true(fullscreenElement.matches(":fullscreen"), "Element has fullscreen flag"); + assert_equals(document.fullscreenElement, fullscreenElement, "Element is fullscreen element"); + document.getElementById("new-parent").appendChild(fullscreenElement); + assert_false(fullscreenElement.matches(":fullscreen"), "Element no longer has fullscreen flag after being moved"); + assert_false(!!document.fullscreenElement, "There is no more fullscreen element, since fullscreen flag was removed"); + await fullScreenChange(); + assert_false(fullscreenElement.matches(":fullscreen"), "Element no longer has fullscreen flag after fullscreen change event"); + assert_false(!!document.fullscreenElement, "There is no more fullscreen element, since fullscreen flag was removed"); + }); +</script> +</html> diff --git a/testing/web-platform/tests/fullscreen/model/move-to-fullscreen-iframe.html b/testing/web-platform/tests/fullscreen/model/move-to-fullscreen-iframe.html new file mode 100644 index 0000000000..0103b2979f --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/move-to-fullscreen-iframe.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<title>Moving fullscreen document's body into a fullscreen iframe</title> +<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="../trusted-click.js"></script> +<iframe allowfullscreen></iframe> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const iframe = document.querySelector("iframe"); + await new Promise((resolve) => { + iframe.onload = resolve; + iframe.src = "about:blank"; + }); + const iframeDoc = iframe.contentDocument; + + // Enter fullscreen for the iframe's body element. + await Promise.all([ + trusted_request(iframeDoc.body, iframeDoc.body), + fullScreenChange(), + ]); + + assert_equals( + document.fullscreenElement, + iframe, + "document's initial fullscreen element" + ); + assert_equals( + iframeDoc.fullscreenElement, + iframeDoc.body, + "iframe's initial fullscreen element" + ); + + // Then, move the outer document's body into the iframe. This is an unusual + // thing to do, but means that the iframe is removed from its document and + // should trigger fullscreen exit. + iframeDoc.documentElement.appendChild(document.body); + + // If we exit in an orderly fashion, that's all one can ask for. + await fullScreenChange(); + assert_equals( + document.fullscreenElement, + null, + "document's final fullscreen element" + ); + + // Because the iframe was removed, its browsing context was discarded and + // its contentDocument has become null. Because that browsing context was + // neither a descendant browsing context nor had an active document, + // nothing at all was done with it in the exit fullscreen algorithm, so + // its fullscreenElement is unchanged. + assert_equals(iframe.contentDocument, null, "iframe's content document"); + assert_equals( + iframeDoc.fullscreenElement, + iframeDoc.body, + "iframe's final fullscreen element" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/move-to-iframe.html b/testing/web-platform/tests/fullscreen/model/move-to-iframe.html new file mode 100644 index 0000000000..d3a7a67298 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/move-to-iframe.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<title>Move the fullscreen element to another document</title> +<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="../trusted-click.js"></script> +<div></div> +<iframe></iframe> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const div = document.querySelector("div"); + const iframe = document.querySelector("iframe"); + const [, event] = await Promise.all([ + trusted_request(div), + fullScreenChange(), + ]); + + assert_equals(document.fullscreenElement, div); + assert_equals(event.target, div); + + assert_equals(div.ownerDocument, document); + iframe.contentDocument.body.appendChild(div); + assert_not_equals(div.ownerDocument, document); + // Moving /div/ removes it from the top layer and thus the fullscreen + // element synchronously becomes null. + assert_equals(document.fullscreenElement, null); + + div.onfullscreenchange = t.unreached_func( + "fullscreenchange fired on element" + ); + iframe.contentDocument.onfullscreenchange = t.unreached_func( + "fullscreenchange fired on other document" + ); + const secondEvent = await fullScreenChange(); + assert_equals(document.fullscreenElement, null); + assert_equals(secondEvent.target, document); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/move-to-inactive-document.html b/testing/web-platform/tests/fullscreen/model/move-to-inactive-document.html new file mode 100644 index 0000000000..b9a95f2954 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/move-to-inactive-document.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>Move the fullscreen element to an inactive document</title> +<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="../trusted-click.js"></script> +<div></div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const div = document.querySelector("div"); + + // Go fullscreen... + await Promise.all([trusted_request(div), fullScreenChange()]); + + const inactiveDocument = document.implementation.createDocument(null, ""); + + div.onfullscreenchange = t.unreached_func( + "fullscreenchange fired on element" + ); + inactiveDocument.onfullscreenchange = t.unreached_func( + "fullscreenchange fired on other document" + ); + + // Transplant element to inactive document... + inactiveDocument.appendChild(div); + + // Fullscreen exits... + await fullScreenChange(); + // Make sure no other events fire... + await new Promise((resolve) => { + requestAnimationFrame(resolve); + }); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/remove-child.html b/testing/web-platform/tests/fullscreen/model/remove-child.html new file mode 100644 index 0000000000..42355dc2da --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/remove-child.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<title>Remove the child of the fullscreen element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="parent"> + <div></div> +</div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const parent = document.getElementById("parent"); + await Promise.all([trusted_request(parent), fullScreenChange()]); + + assert_equals(document.fullscreenElement, parent); + parent.textContent = ""; // removes all children + // The fullscreen element should not be affected. + assert_equals(document.fullscreenElement, parent); + document.onfullscreenchange = t.unreached_func("fullscreenchange event"); + // A fullscreenchange event would be fired after an async section + // and an animation frame task, so wait until after that. + await new Promise((resolve) => { + requestAnimationFrame(resolve); + }); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/remove-first.html b/testing/web-platform/tests/fullscreen/model/remove-first.html new file mode 100644 index 0000000000..b4058db320 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/remove-first.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<title>Remove the first element on the fullscreen element stack</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="first"> + <div id="last"></div> +</div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const first = document.getElementById("first"); + + const [, firstEvent] = await Promise.all([ + trusted_request(first), + fullScreenChange(), + ]); + assert_equals(document.fullscreenElement, first); + assert_equals(firstEvent.target, first); + + const last = document.getElementById("last"); + const [, secondEvent] = await Promise.all([ + trusted_request(last), + fullScreenChange(), + ]); + assert_equals(document.fullscreenElement, last); + assert_equals(event.target, last); + first.remove(); + + // Both /first/ and /last/ were removed from the top layer and + // thus the fullscreen element synchronously becomes null. + assert_equals(document.fullscreenElement, null); + + const thirdEvent = await fullScreenChange(); + assert_equals(document.fullscreenElement, null); + assert_equals(event.target, document); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/remove-last.html b/testing/web-platform/tests/fullscreen/model/remove-last.html new file mode 100644 index 0000000000..760ccaa0ba --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/remove-last.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<title>Remove the last element on the fullscreen element stack</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="first"> + <div id="last"></div> +</div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const first = document.getElementById("first"); + const [, firstEvent] = await Promise.all([ + trusted_request(first), + fullScreenChange(), + ]); + + assert_equals(document.fullscreenElement, first); + assert_equals(firstEvent.target, first); + + const last = document.getElementById("last"); + const [, lastEvent] = await Promise.all([ + trusted_request(last), + fullScreenChange(), + ]); + + assert_equals(document.fullscreenElement, last); + assert_equals(event.target, last); + last.remove(); + // Because /last/ was removed from the top layer, we exit + // fullscreen element synchronously. + assert_equals(document.fullscreenElement, first); + + const finalEvent = await fullScreenChange(); + // fullscreen change element should be queued against the + // document target. + assert_equals(document.fullscreenElement, null); + assert_equals(event.target, document); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/remove-parent.html b/testing/web-platform/tests/fullscreen/model/remove-parent.html new file mode 100644 index 0000000000..54ff5b8371 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/remove-parent.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Remove the parent of the fullscreen element</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div> + <div id="child"></div> +</div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const child = document.getElementById("child"); + const [, event] = await Promise.all([ + trusted_request(child), + fullScreenChange(), + ]); + assert_equals(document.fullscreenElement, child); + assert_equals(event.target, child); + child.parentNode.remove(); + // Because /child/ was removed from the top layer, the fullscreen + // element becomes null synchronously. + assert_equals(document.fullscreenElement, null); + const secondEvent = await fullScreenChange(); + assert_equals(document.fullscreenElement, null); + assert_equals(secondEvent.target, document); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/model/remove-single.html b/testing/web-platform/tests/fullscreen/model/remove-single.html new file mode 100644 index 0000000000..0401f77953 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/model/remove-single.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Remove the single element on the fullscreen element stack</title> +<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="../trusted-click.js"></script> +<div id="log"></div> +<div id="single"></div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const single = document.getElementById("single"); + const [, event] = await Promise.all([ + trusted_request(single), + fullScreenChange(), + ]); + + assert_equals(document.fullscreenElement, single); + assert_equals(event.target, single); + single.remove(); + // Because /single/ was removed from the top layer, the fullscreen + // element becomes null synchronously. + assert_equals(document.fullscreenElement, null); + + const secondEvent = await fullScreenChange(); + assert_equals(document.fullscreenElement, null); + assert_equals(event.target, single); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/backdrop-iframe-ref.html b/testing/web-platform/tests/fullscreen/rendering/backdrop-iframe-ref.html new file mode 100644 index 0000000000..3126fe1942 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/backdrop-iframe-ref.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<body style="background: green"></body> diff --git a/testing/web-platform/tests/fullscreen/rendering/backdrop-iframe.html b/testing/web-platform/tests/fullscreen/rendering/backdrop-iframe.html new file mode 100644 index 0000000000..710d1b48f1 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/backdrop-iframe.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>::backdrop for a fullscreen iframe element</title> +<link rel=match href="backdrop-iframe-ref.html"> +<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<style> +iframe::backdrop { + background: green; +} +</style> +<iframe></iframe> +<script> +document.addEventListener('fullscreenchange', () => { + document.documentElement.classList.remove('reftest-wait'); +}); +test_driver.bless('fullscreen', () => { + document.querySelector('iframe').requestFullscreen(); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/backdrop-object-ref.html b/testing/web-platform/tests/fullscreen/rendering/backdrop-object-ref.html new file mode 100644 index 0000000000..6c7071a727 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/backdrop-object-ref.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<style> +body { + background: blue; + margin: 0; +} +div { + position: fixed; + width: 100px; + height: 100px; + background: green; +} +</style> +<div></div> diff --git a/testing/web-platform/tests/fullscreen/rendering/backdrop-object.html b/testing/web-platform/tests/fullscreen/rendering/backdrop-object.html new file mode 100644 index 0000000000..be285b7612 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/backdrop-object.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>::backdrop for a fullscreen object element</title> +<link rel=match href="backdrop-object-ref.html"> +<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<style> +object::backdrop { + background: blue; +} +</style> +<object width="200" type="image/svg+xml" data="../../images/100px-green-rect.svg"></object> +<script> +const object = document.querySelector("object"); +Promise.all([ + new Promise((resolve, reject) => document.addEventListener("fullscreenchange", resolve)), + new Promise((resolve, reject) => object.addEventListener("load", resolve)) +]).then(() => document.documentElement.classList.remove('reftest-wait')); + +test_driver.bless('fullscreen', () => object.requestFullscreen()); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-css-invalidation.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-css-invalidation.html new file mode 100644 index 0000000000..e855d0c193 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-css-invalidation.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Invalidate :fullscreen based style</title> +<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> +<style> + #pass { + color: red; + } + :root:fullscreen #pass { + color: green; + } +</style> +<div id="pass">Should be green</div> +<script> + async_test(t => { + document.onfullscreenchange = t.step_func_done(() => { + assert_equals(document.fullscreenElement, document.documentElement); + assert_equals(getComputedStyle(pass).color, "rgb(0, 128, 0)", "Green when :root is fullscreened."); + }); + document.documentElement.addEventListener('click', t.step_func(() => { + document.documentElement.requestFullscreen(); + }), {once: true}); + assert_equals(getComputedStyle(pass).color, "rgb(255, 0, 0)", "Initially red."); + test_driver.click(document.documentElement); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-css-transition.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-css-transition.html new file mode 100644 index 0000000000..b494dc04e6 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-css-transition.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Transitions should not be stopped by going fullscreen</title> +<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> +<style> + #trans { + transition: color steps(1, end) 100s; + color: green; + } +</style> +<div id="trans">Should be green</div> +<script> + async_test(t => { + document.onfullscreenchange = t.step_func_done(() => { + assert_equals(document.fullscreenElement, trans); + assert_equals(getComputedStyle(trans).color, "rgb(0, 128, 0)", "Transition is in progress - still green"); + }); + trans.addEventListener('click', t.step_func(() => { + trans.style.color = "red"; + trans.offsetTop; + trans.requestFullscreen(); + }), {once: true}); + test_driver.click(trans); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-pseudo-class-support.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-pseudo-class-support.html new file mode 100644 index 0000000000..fb2ff318b9 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-pseudo-class-support.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<title>:fullscreen pseudo-class support</title> +<link rel="help" href="https://fullscreen.spec.whatwg.org/#:fullscreen-pseudo-class"> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-element-matches"> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-parentnode-queryselector"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +// This is a separate test so that support for :fullscreen can be detected +// without actually going fullscreen. If it were not supported, then this test +// would fail. +test(t => { + // precondition is to throw for unknown pseudo-classes: + assert_throws_dom("SyntaxError", () => document.body.matches(':halfscreen')); + assert_throws_dom("SyntaxError", () => document.querySelector(':halfscreen')); + // the actual test: + assert_false(document.body.matches(':fullscreen')); + assert_equals(document.querySelector(':fullscreen'), null); +}); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-pseudo-class.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-pseudo-class.html new file mode 100644 index 0000000000..5b02c32ef3 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-pseudo-class.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<title>:fullscreen pseudo-class</title> +<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="../trusted-click.js"></script> +<div><div></div></div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const outer = document.querySelector("div"); + const inner = outer.firstChild; + + // First request fullscreen for the outer element. + await trusted_request(outer); + await fullScreenChange(); + assert_equals(document.fullscreenElement, outer); + assert_true( + outer.matches(":fullscreen"), + "outer:fullscreen in simple fullscreen" + ); + assert_false( + inner.matches(":fullscreen"), + "inner:fullscreen in simple fullscreen" + ); + + // Then request fullscreen for the inner element. + await trusted_request(inner); + // Although inner is the fullscreen element, both elements match the + // selector, as both have their fullscreen flag set. + assert_equals(document.fullscreenElement, inner); + assert_true( + inner.matches(":fullscreen"), + "inner:fullscreen in nested fullscreen" + ); + assert_true( + outer.matches(":fullscreen"), + "outer:fullscreen in nested fullscreen" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-block-scroll.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-block-scroll.html new file mode 100644 index 0000000000..87147b42e0 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-block-scroll.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<style> + body { + height: 10000px; + background: grey; + } +</style> +<title>fullscreen root block scrolling</title> +<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="../trusted-click.js"></script> +<body> +<div> + This page tests that entering fullscreen doesn't adjust the scroll offset +</div> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + await trusted_click(); + document.scrollingElement.scrollTop = 300; + await document.documentElement.requestFullscreen(); + await fullScreenChange(); + + assert_equals(document.fullscreenElement, document.documentElement); + assert_not_equals(document.scrollingElement.scrollTop, 0); + document.scrollingElement.scrollTop = 0; + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-block-size.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-block-size.html new file mode 100644 index 0000000000..5138494d5d --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-block-size.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<style> + html, + body { + margin: 0px; + } +</style> +<title>fullscreen root block sizing</title> +<!-- This page intentionally has no content. It needs to have +no width or height. This is to ensure that the root element +gets sizing in fullscreen mode as it does in as it does not +in fullscreen mode. +--> +<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="../trusted-click.js"></script> +<body></body> +<script> + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + await trusted_click(); + await document.documentElement.requestFullscreen(); + await fullScreenChange(); + assert_equals(document.fullscreenElement, document.documentElement); + assert_true(document.documentElement.getBoundingClientRect().width > 0); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-fills-page-ref.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-fills-page-ref.html new file mode 100644 index 0000000000..b2bf13557a --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-fills-page-ref.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> + <style> + html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + } + + body { + background-color: green; + } + </style> +</head> +<body></body> +</html> diff --git a/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-fills-page.html b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-fills-page.html new file mode 100644 index 0000000000..f122e678f3 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/fullscreen-root-fills-page.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<head> + <link rel="author" href="https://github.com/nt1m"> + <link rel="match" href="fullscreen-root-fills-page-ref.html"> + <style> + html { + background-color: red; + height: 100%; + overflow: hidden; + + /* These should be no-op */ + top: 200px; + left: 200px; + right: 200px; + bottom: 200px; + } + + html, body { + margin: 0; + padding: 0; + } + + body, #cover { + height: 100%; + width: 100%; + } + + #cover { + background-color: green; + } + </style> +</head> + +<body> + <div id="cover"></div> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <script> + document.addEventListener("fullscreenchange", () => { + document.documentElement.classList.remove("reftest-wait"); + }); + test_driver.bless("fullscreen") + .then(() => document.documentElement.requestFullscreen()) + </script> +</body> +</html> diff --git a/testing/web-platform/tests/fullscreen/rendering/ua-style-iframe.html b/testing/web-platform/tests/fullscreen/rendering/ua-style-iframe.html new file mode 100644 index 0000000000..dcf1656e00 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/rendering/ua-style-iframe.html @@ -0,0 +1,80 @@ +<!DOCTYPE html> +<title>User-agent levels style sheet defaults for iframe</title> +<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="../trusted-click.js"></script> +<style> + iframe { + border: 1px solid blue; + padding: 1px; + /* transform is also tested because of https://crbug.com/662393 */ + transform: scale(0.5); + } +</style> +<div id="log"></div> +<div id="ancestor"><iframe></iframe></div> +<script> + function assert_dir_properties(style, propBase, value, state) { + for (let dir of ["Top", "Right", "Bottom", "Left"]) { + let prop = propBase.replace("{}", dir); + assert_equals(style[prop], value, `${state} ${prop} style`); + } + } + + promise_test(async (t) => { + t.add_cleanup(() => { + if (document.fullscreenElement) { + return document.exitFullscreen(); + } + }); + const ancestor = document.getElementById("ancestor"); + const iframe = ancestor.firstChild; + + const initialStyle = getComputedStyle(iframe); + assert_dir_properties(initialStyle, "border{}Width", "1px", "initial"); + assert_dir_properties(initialStyle, "border{}Style", "solid", "initial"); + assert_dir_properties( + initialStyle, + "border{}Color", + "rgb(0, 0, 255)", + "initial" + ); + assert_dir_properties(initialStyle, "padding{}", "1px", "initial"); + assert_equals( + initialStyle.transform, + "matrix(0.5, 0, 0, 0.5, 0, 0)", + "initial transform style" + ); + + await trusted_request(iframe); + await fullScreenChange(); + + const fullscreenStyle = getComputedStyle(iframe); + assert_dir_properties( + fullscreenStyle, + "border{}Width", + "0px", + "fullscreen" + ); + assert_dir_properties( + fullscreenStyle, + "border{}Style", + "none", + "fullscreen" + ); + assert_dir_properties( + fullscreenStyle, + "border{}Color", + "rgb(0, 0, 0)", + "fullscreen" + ); + assert_dir_properties(fullscreenStyle, "padding{}", "0px", "fullscreen"); + assert_equals( + fullscreenStyle.transform, + "none", + "fullscreen transform style" + ); + }); +</script> diff --git a/testing/web-platform/tests/fullscreen/trusted-click.js b/testing/web-platform/tests/fullscreen/trusted-click.js new file mode 100644 index 0000000000..51fbce7ee4 --- /dev/null +++ b/testing/web-platform/tests/fullscreen/trusted-click.js @@ -0,0 +1,65 @@ +/** + * Invokes callback from a trusted click event, avoiding interception by fullscreen element. + * + * @param {Element} container - Element where button will be created and clicked. + */ +function trusted_click(container = document.body) { + var document = container.ownerDocument; + var button = document.createElement("button"); + button.textContent = "click to continue test"; + button.style.display = "block"; + button.style.fontSize = "20px"; + button.style.padding = "10px"; + button.addEventListener("click", () => { + button.remove(); + }); + container.appendChild(button); + if (window.top !== window) test_driver.set_test_context(window.top); + // Race them for manually testing... + return Promise.race([ + test_driver.click(button), + new Promise((resolve) => { + button.addEventListener("click", resolve); + }), + ]); +} + +// Invokes element.requestFullscreen() from a trusted click. +async function trusted_request(element = document.body, whereToCreateButton = null) { + await trusted_click(whereToCreateButton ?? element.parentNode ?? element); + return element.requestFullscreen(); +} + +/** + * Used to await a fullscreen change event, once. + * + * @param {EventTarget} target + * @returns + */ +function fullScreenChange(target = document) { + return new Promise((resolve) => + target.addEventListener("fullscreenchange", resolve, { once: true }) + ); +} + +/** + * Sets up a message event listener, and returns a promise that resolves + * when the message from the iframe is received. + * + * @param {HTMLIFrameElement} iframe + * @returns {Promise<object>} + */ +function promiseMessage(iframe) { + return new Promise((resolve) => { + window.addEventListener( + "message", + (e) => { + if (e.data?.report.api === "fullscreen") { + resolve(e.data); + } + }, + { once: true } + ); + iframe.contentWindow.postMessage({ action: "report" }, "*"); + }); +} |