diff options
Diffstat (limited to 'testing/web-platform/tests/visual-viewport')
31 files changed, 2276 insertions, 0 deletions
diff --git a/testing/web-platform/tests/visual-viewport/META.yml b/testing/web-platform/tests/visual-viewport/META.yml new file mode 100644 index 0000000000..5499f77335 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/META.yml @@ -0,0 +1,3 @@ +spec: https://wicg.github.io/visual-viewport/ +suggested_reviewers: + - bokand diff --git a/testing/web-platform/tests/visual-viewport/helper-resize-event-on-load-overflowing-page.html b/testing/web-platform/tests/visual-viewport/helper-resize-event-on-load-overflowing-page.html new file mode 100644 index 0000000000..c036b16ec8 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/helper-resize-event-on-load-overflowing-page.html @@ -0,0 +1,47 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Resize Event On Load Overflowing Page</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script> + var opener = window.opener; + var numViewResizes = 0; + window.visualViewport.addEventListener('resize', function() { + numViewResizes++; + }); + + window.addEventListener('load', function() { + requestAnimationFrame(function() { + requestAnimationFrame( + opener.t.step_func_done(function() { + var isOverlay = opener.calculateScrollbarThickness() == 0; + opener.assert_equals(numViewResizes, isOverlay ? 0 : 1); + })); + }); + }); + </script> + <style> + html { + height: 100%; + } + body { + /* Ensure overflow */ + height: 200%; + } + #log { + overflow: auto; + } + </style> + </head> + <body> + <h1>Viewport: Resize Event On Load Overflowing Page</h1> + <h4> + Test Description: This test ensures that we fire a resize event against + window.visualViewport if the page has overflow (since this creates a scrollbar + and thus changes the viewport size). + </h4> + <div id="log"></div> + </body> +</html> + diff --git a/testing/web-platform/tests/visual-viewport/page-and-offset-in-iframe.html b/testing/web-platform/tests/visual-viewport/page-and-offset-in-iframe.html new file mode 100644 index 0000000000..086c816956 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/page-and-offset-in-iframe.html @@ -0,0 +1,86 @@ +<!doctype html> +<html> + <head> + <title>Viewport: page and offset values in iframe</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <script src="viewport_support.js"></script> + <style> + iframe { + width: 200px; + height: 300px; + border: 0; + } + </style> + </head> + <body> + <h1>Viewport: Page and offset values in iframe</h1> + <h4> + Test Description: This test checks for correct visualViewport values in + an iframe. + </h4> + <iframe></iframe> + </body> + <script> + var iframe = frames[0].window; + + // Add overflow to the iframe so it can scroll. + iframe.document.body.style.width = "2000px"; + iframe.document.body.style.height = "2000px"; + iframe.scrollTo(1000, 1200); + + promise_test(async t => { + assert_equals(visualViewport.scale, 1, + "[PRECONDITION] Start off unzoomed"); + assert_equals(visualViewport.offsetLeft, 0, + "[PRECONDITION] No offsetLeft to start"); + assert_equals(visualViewport.offsetTop, 0, + "[PRECONDITION] No offsetTop to start"); + + // The iframe's visual viewport isn't yet offset + assert_equals(iframe.visualViewport.offsetLeft, 0, + "offsetLeft must be 0"); + assert_equals(iframe.visualViewport.offsetTop, 0, + "offsetTop must be 0"); + + // However, page values should reflect layout viewport scrolling. + assert_equals(iframe.visualViewport.pageLeft, 1000, + "pageLeft must reflect location in document."); + assert_equals(iframe.visualViewport.pageTop, 1200, + "pageTop must reflect location in document."); + + // Zoom in and pan the viewport to ensure the iframe is independent + // of the root frame. + await pinchZoomIn(); + + // These values are arbitrary since the amount of pinch-zoom caused + // by pinchZoomIn will differ but we only care that the iframe's + // values aren't changed. + assert_greater_than(visualViewport.scale, 1.2, + "Pinch zoom must have increased scale"); + assert_greater_than(visualViewport.offsetLeft, 10, + "Pinch zoom must have offsetLeft visualViewport"); + assert_greater_than(visualViewport.offsetTop, 10, + "Pinch zoom must have offsetTop visualViewport"); + + // The iframe's visualViewport is independent of the root frame's so + // none of the values should have changed. + assert_equals(iframe.visualViewport.offsetLeft, 0, + "After zooming, offsetLeft must remain 0"); + assert_equals(iframe.visualViewport.offsetTop, 0, + "After zooming, offsetTop must remain 0"); + assert_equals(iframe.visualViewport.pageLeft, 1000, + "After zooming, pageLeft must reflect location in document."); + assert_equals(iframe.visualViewport.pageTop, 1200, + "After zooming, pageTop must reflect location in document."); + + assert_equals(iframe.visualViewport.scale, 1, + "Iframe's visualViewport must not be scaled"); + }, "VisualViewport page and offset values in iframe"); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/resize-event-order.html b/testing/web-platform/tests/visual-viewport/resize-event-order.html new file mode 100644 index 0000000000..41a13728bc --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/resize-event-order.html @@ -0,0 +1,72 @@ +<!doctype html> +<title>Visual Viewport Resize Event Order</title> +<meta charset=utf-8> +<link rel="help" href="https://wicg.github.io/visual-viewport/index.html"> +<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> + iframe { + width: 300px; + height: 300px; + } +</style> + +<body> + <iframe srcdoc="<!DOCTYPE html>"></iframe> +</body> + +<script> + +async function oneRaf(win) { + return new Promise((resolve) => { + win.requestAnimationFrame(resolve); + }); +} + +// Runs the test on the given window object, asserts that event handlers on the +// DOMWindow object are fired before those on the VisualViewport object. +// `resizeFunc` is used to perform the resize. +async function runTest(win, resizeFunc) { + const resize_events = []; + + win.onresize = () => { resize_events.push('window-attribute'); } + win.addEventListener('resize', () => { resize_events.push('window-addEventListener'); }); + win.visualViewport.onresize = () => { resize_events.push('visualViewport-attribute'); } + win.visualViewport.addEventListener('resize', () => { + resize_events.push('visualViewport-addEventListener'); }); + + assert_equals(resize_events.toString(), '', 'PRECONDITION'); + resizeFunc(500, 600); + + await oneRaf(win); + + assert_equals(resize_events.toString(), + 'window-attribute,window-addEventListener,' + + 'visualViewport-attribute,visualViewport-addEventListener'); +} + +onload = () => { + // Test the event order in a top-level window which we will programmatically + // resize. + promise_test(async t => { + let popup = null; + test_driver.bless('Open a popup in a new window', () => { + popup = window.open('about:blank', 'newwindow', 'width=300,height=300'); + }); + await t.step_wait(() => popup != null, "Opened popup window"); + + await runTest(popup, (x, y) => {popup.resizeTo(x, y);}); + }, 'Popup: DOMWindow resize fired before VisualViewport.'); + + // Also test the resize resulting from an iframe's size change. + promise_test(async t => { + const iframe = frames[0]; + await runTest(iframe, (x, y) => {iframe.frameElement.style.width = x + 'px'; + iframe.frameElement.style.height = y + 'px'; + iframe.frameElement.offsetWidth; /* force reflow */}); + }, 'iframe: DOMWindow resize fired before VisualViewport.'); +} + +</script> diff --git a/testing/web-platform/tests/visual-viewport/scroll-event-order.html b/testing/web-platform/tests/visual-viewport/scroll-event-order.html new file mode 100644 index 0000000000..da5b77c0e2 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/scroll-event-order.html @@ -0,0 +1,98 @@ +<!doctype html> +<title>Visual Viewport Scroll Event Order</title> +<meta charset=utf-8> +<link rel="help" href="https://wicg.github.io/visual-viewport/index.html"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="viewport_support.js"></script> +<style> + #target { + width: 100px; + height: 100px; + background-color: red; + position: absolute; + top: 300vh; + } + + #scroller1,#scroller2 { + width: 200px; + height: 200px; + overflow: auto; + } + + #spacer { + width: 80px; + height: 1000px; + background-image: linear-gradient(45deg, #808080 25%, transparent 25%), + linear-gradient(-45deg, #808080 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #808080 75%), + linear-gradient(-45deg, transparent 75%, #808080 75%); + background-size: 40px 40px; + background-position: 0 0, 0 20px, 20px -20px, -20px 0px; + } +</style> + +<body> + <div id="target"></div> + <div id="scroller1"><div id="spacer"></div></div> + <div id="scroller2"><div id="spacer"></div></div> +</body> + +<script> + +async function oneRaf() { + return new Promise((resolve) => { + window.requestAnimationFrame(resolve); + }); +} + +const scroller1 = document.getElementById('scroller1'); +const scroller2 = document.getElementById('scroller2'); + +promise_test(async t => { + // Pinch-zoom in so that the scrollIntoView call below causes scrolling in + // both the layout and visual viewports within the same rAF. + await pinchZoomIn(); + assert_greater_than(window.visualViewport.scale, 1, 'Must have zoomed in'); + + await oneRaf(); + + const scroll_events = []; + + // Register the scroll handlers on the window, visualViewport, and both + // <div> scrollers. + { + window.onscroll = () => { scroll_events.push('window-attribute'); } + window.addEventListener('scroll', () => { scroll_events.push('window-addEventListener'); }); + window.visualViewport.onscroll = () => { scroll_events.push('visualViewport-attribute'); } + window.visualViewport.addEventListener('scroll', () => { + scroll_events.push('visualViewport-addEventListener'); }); + scroller1.addEventListener('scroll', + () => { scroll_events.push('scroller1'); }); + scroller2.addEventListener('scroll', + () => { scroll_events.push('scroller2'); }); + } + + // Cause scrolling in each scroller and scrollIntoView so that the layout + // and visual viewports both scroll. + scroller1.scrollTop = 200; + document.getElementById('target').scrollIntoView(); + scroller2.scrollTop = 200; + + // Wait a rAF since scroll events are delievered as part of the event loop. + await oneRaf(); + + // The scroll events must be delivered in the order they were executed, + // scroller1 first, then the viewport (window then visualViewport), then + // scroller2. + assert_equals(scroll_events.toString(), + 'scroller1,' + + 'window-attribute,window-addEventListener,' + + 'visualViewport-attribute,visualViewport-addEventListener,' + + 'scroller2'); +}, "Scroll event ordering"); + +</script> diff --git a/testing/web-platform/tests/visual-viewport/viewport-attribute-event-handlers-manual.html b/testing/web-platform/tests/visual-viewport/viewport-attribute-event-handlers-manual.html new file mode 100644 index 0000000000..896f6cd98b --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-attribute-event-handlers-manual.html @@ -0,0 +1,75 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Attribute event handlers test</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_timeout: true, explicit_done: true}) + </script> + </head> + <body> + <h1>Viewport: Attribute event handlers test</h1> + <h4> + Test Description: This test checks that attribute event handlers function correctly. + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + var didFireResize = false; + var didFireScroll = false; + + addManualTestStep( + function() { + test(() => { + assert_not_equals(typeof(window.visualViewport.onresize), + 'undefined', + 'onresize is defined'); + assert_not_equals(typeof(window.visualViewport.onscroll), + 'undefined', + 'onscroll is defined'); + }, 'Attribute event handlers defined'); + + window.visualViewport.onresize = function(e) { + didFireResize = true; + }; + window.visualViewport.onscroll = function(e) { + didFireScroll = true; + }; + }, + null, + '1. Pinch-zoom into the screen anywhere by any amount.'); + + addManualTestStep( + function() { + test(() => { + assert_true(didFireResize, 'Resize event fired'); + assert_true(didFireScroll, 'Scroll event fired'); + }, 'Event handler functionality'); + continueBtn.remove(); + }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html b/testing/web-platform/tests/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html new file mode 100644 index 0000000000..8fcbfe1391 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html @@ -0,0 +1,158 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Dimensions with custom scrollbars</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_done: true, explicit_timeout: true}); + </script> + <style> + #spacer { + width: 10000px; + height: 10000px; + position: absolute; + visibility: hidden; + } + ::-webkit-scrollbar { + width: 20px; + height: 25px; + } + + ::-webkit-scrollbar-track { + background-color: #b46868; + } + + ::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.2); + } + </style> + </head> + <body> + <h1>Viewport: Dimensions with custom scrollbars</h1> + <h4> + Test Description: Tests the viewport dimensions correctly account for + custom scrollbars + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip</button> + <p> + Skip this test if your browser doesn't support custom scrollbars or + browser-zoom (Ctrl+/-). + </p> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + <div id="spacer"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + var originalWidth = 0; + var originalHeight = 0; + var originalInnerWidth = 0; + var originalInnerHeight = 0; + + addManualTestStep( + function() {}, + null, + '1. Ensure the browser is at the default pinch and browser zoom ' + + 'levels (100%). Most browsers: ctrl+0'); + + addManualTestStep( + function() { + originalWidth = window.visualViewport.width; + originalHeight = window.visualViewport.height; + // Remember the inner dimensions here for the next test to + // address an edge case where originalInnerWidth is an odd + // number of pixels. The test expects that at 2x browser-zoom, + // visualViewport.width = innerWidth - customScrollbarThickness + // The equality only holds if originalInnerWidth / innerWidth is + // exactly 2, which is not the case in the aforementioned + // scenario because innerWidth always has to be an integer + // number of CSS pixels. Ditto for the height computation. + originalInnerWidth = window.innerWidth; + originalInnerHeight = window.innerHeight; + + assert_equals( + window.visualViewport.width, + window.innerWidth - 20, + "Custom scrollbar width subtracted from viewport."); + assert_equals( + window.visualViewport.height, + window.innerHeight - 25, + "Custom scrollbar height subtracted from viewport."); + }, + 'No zoom or scale applied', + '2. Browser-zoom into 200% (ctrl +)'); + + addManualTestStep( + function() { + // Ensure we zoomed in to about what we expect. + assert_approx_equals( + originalInnerWidth / window.innerWidth, + 2.0, + 0.1, + "Browser zoom to correct level"); + + // The custom scrollbars are also 2x larger on the screen, so + // the viewport is smaller than half of the original size. + assert_equals( + window.visualViewport.width, + originalInnerWidth / 2 - 20, + "Custom scrollbar width subtracted from viewport."); + assert_equals( + window.visualViewport.height, + originalInnerHeight / 2 - 25, + "Custom scrollbar height subtracted from viewport."); + }, + 'With 200% browser zoom', + '3. Reset browser zoom (ctrl+0).'); + + addManualTestStep( + showPinchWidget.bind(null, 2.0, 0, 0, continueTest), + null, + 'Pinch-zoom dialog in progress'); + + addManualTestStep( + function() { + assert_approx_equals( + window.visualViewport.scale, 2, 0.2, "Pinch zoom to correct scale"); + + // Scrollbars do not grow with pinch-zoom so they take up fewer + // CSS pixels as you zoom in. + assert_approx_equals( + window.visualViewport.width, + originalWidth / window.visualViewport.scale, + 1, + "Custom scrollbar width subtracted from viewport."); + assert_approx_equals( + window.visualViewport.height, + originalHeight / window.visualViewport.scale, + 1, + "Custom scrollbar width subtracted from viewport."); + }, + 'With ~200% pinch zoom', + '4. Pinch-zoom out.'); + + addManualTestStep( + function() { continueBtn.remove(); }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-dimensions-scrollbars-manual.html b/testing/web-platform/tests/visual-viewport/viewport-dimensions-scrollbars-manual.html new file mode 100644 index 0000000000..493de254dc --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-dimensions-scrollbars-manual.html @@ -0,0 +1,146 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Dimensions with scrollbars</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_done: true, explicit_timeout: true}); + </script> + <style> + #spacer { + width: 10000px; + height: 10000px; + position: absolute; + visibility: hidden; + } + </style> + </head> + <body> + <h1>Viewport: Dimensions with scrollbars</h1> + <h4> + Test Description: Tests the viewport dimensions correctly account for + scrollbars + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + <p> + If your browser doesn't support browser-zoom (Ctrl+/-, e.g. Mobile + Browsers) please skip. + </p> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + <div id="spacer"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + var scrollbarThickness = calculateScrollbarThickness(); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + var originalWidth = 0; + var originalHeight = 0; + var originalInnerWidth = 0; + var originalVisualViewportWidthExpectation = 0; + var originalVisualViewportHeightExpectation = 0; + + addManualTestStep( + function() {}, + null, + '1. Ensure the browser is at the default pinch and browser zoom ' + + 'levels (100%). Most browsers: ctrl+0'); + + addManualTestStep( + function() { + originalWidth = window.visualViewport.width; + originalHeight = window.visualViewport.height; + originalInnerWidth = window.innerWidth; + // Remember the visualViewport size here for the next test to + // address an edge case where originalInnerWidth is an odd + // number of pixels. The test expects that at 2x browser-zoom, + // visualViewport.width = innerWidth - scrollbarThickness / 2.0 + // The equality only holds if originalInnerWidth / innerWidth is + // exactly 2, which is not the case in the aforementioned + // scenario because innerWidth always has to be an integer + // number of CSS pixels. Ditto for the height computation. + originalVisualViewportWidthExpectation = + window.innerWidth - scrollbarThickness; + originalVisualViewportHeightExpectation = + window.innerHeight - scrollbarThickness; + + assert_equals( + window.visualViewport.width, + originalVisualViewportWidthExpectation, + "Scrollbar width subtracted from viewport."); + assert_equals( + window.visualViewport.height, + originalVisualViewportHeightExpectation, + "Scrollbar height subtracted from viewport."); + }, + 'No zoom or scale applied', + '2. Browser-zoom into 200% (ctrl +)'); + + addManualTestStep( + function() { + assert_approx_equals( + originalInnerWidth / window.innerWidth, + 2.0, + 0.1, + "Browser zoom to correct level"); + + // Scrollbars on the window don't grow with browser-zoom so + // they'll be fewer CSS pixels as the user zooms in. + assert_equals( + window.visualViewport.width, + originalVisualViewportWidthExpectation / 2, + "Scrollbar width subtracted from viewport."); + assert_equals( + window.visualViewport.height, + originalVisualViewportHeightExpectation / 2, + "Scrollbar height subtracted from viewport."); + }, + 'With 200% browser zoom', + '3. Reset browser zoom (ctrl+0).'); + + addManualTestStep( + showPinchWidget.bind(null, 2.0, 0, 0, continueTest), + null, + 'Pinch-zoom dialog in progress'); + + addManualTestStep( + function() { + assert_approx_equals( + window.visualViewport.scale, 2, 0.2, "Pinch zoom to correct scale"); + + assert_approx_equals(window.visualViewport.width, + originalWidth / window.visualViewport.scale, + 1, + "Scrollbar width subtracted from viewport."); + assert_approx_equals(window.visualViewport.height, + originalHeight / window.visualViewport.scale, + 1, + "Scrollbar width subtracted from viewport."); + }, + 'With ~200% pinch zoom', + '4. Pinch-zoom out.'); + + addManualTestStep( + function() { continueBtn.remove(); }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-no-resize-event-on-overflow-recalc.html b/testing/web-platform/tests/visual-viewport/viewport-no-resize-event-on-overflow-recalc.html new file mode 100644 index 0000000000..dcb9432da8 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-no-resize-event-on-overflow-recalc.html @@ -0,0 +1,50 @@ +<!doctype html> +<html> + <head> + <title>Viewport: No Resize Event Fired on Overflow Recalc</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <style> + html { + height: 100%; + } + body { + /* Ensure overflow to start */ + height: 200%; + } + </style> + </head> + <body> + <h1>No Resize Event Fired on Overflow Recalc</h1> + <h4> + Test Description: This test ensures we don't fire spurrious resize + events when overflow is recalculated. + </h4> + <script> + function runTest() { + var t = async_test( + "Resize event not fired at window.visualViewport when content is added"); + var viewResized = false; + window.visualViewport.addEventListener('resize', function() { + viewResized = true; + }); + + requestAnimationFrame(t.step_func_done(function() { + assert_equals(viewResized, false); + })); + + document.body.style.height = "400%"; + } + + // Run the test after load to make sure any resize from load doesn't + // interfere. + window.onload = requestAnimationFrame(function() { + requestAnimationFrame(runTest); + }); + </script> + <div id="log"></div> + </body> +</html> + diff --git a/testing/web-platform/tests/visual-viewport/viewport-offset-manual.html b/testing/web-platform/tests/visual-viewport/viewport-offset-manual.html new file mode 100644 index 0000000000..c216e405a3 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-offset-manual.html @@ -0,0 +1,151 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Offset</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_done: true, explicit_timeout: true}); + </script> + <style> + html { + width: 100%; + height: 100%; + } + #fullscreenBox { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + visibility: hidden; + } + </style> + </head> + <body> + <h1>Viewport: Offset</h1> + <h4> + Test Description: Tests the offset scrolling properties on an + unscrollable page. + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <h4>Instruction</h4> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + <div id="fullscreenBox"> + <!-- Invisible but needed to get maximum scrollable extents in the + presence of a collapsible URL bar. --> + </div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + // Prevent scrolling (though there should be no overflow) so that all + // scrolling must happen as panning the visual viewport within the + // layout viewport. + document.documentElement.style.overflow = "hidden"; + + addManualTestStep( + function() {}, + null, + '1. Ensure the browser is at the default pinch and browser zoom ' + + 'levels (100%). Most browsers: ctrl+0'); + + var scale = 3.0; + var xTarget = 2 * window.innerWidth / scale; + var yTarget = 2 * window.innerHeight / scale; + addManualTestStep( + showPinchWidget.bind(null, scale, xTarget, yTarget, continueTest), + null, + '2.Follow instructions on pinch zoom dialog.'); + + addManualTestStep( + function() { + var actualScale = window.visualViewport.scale; + var actualOffsetLeft = window.visualViewport.offsetLeft; + var actualOffsetTop = window.visualViewport.offsetTop; + + // This needs to happen before assertions in case they fail. A + // failed assertion stops running this function. + window.scrollTo(0, 0); + + // Ensure we zoomed in to about what we expect. + assert_approx_equals(actualScale, scale, 0.2, + "window.visualViewport.scale reflects pinch-zoom level"); + assert_approx_equals(actualOffsetLeft, xTarget, 5, + "offsetLeft value is correct."); + assert_approx_equals(actualOffsetTop, yTarget, 5, + "offsetTop value is correct."); + }, + 'With ~300% pinch-zoom', + '3. Pinch-zoom back out to the minimum scale'); + + addManualTestStep( + showPinchWidget.bind(null, 2, 0, 0, continueTest), + null, + '4.Follow instructions on pinch zoom dialog.'); + + addManualTestStep( + function() { + document.documentElement.style.overflow = ""; + continueBtn.style.position = "absolute"; + continueBtn.style.left = "150%"; + continueBtn.style.top = "150%"; + + assert_approx_equals(window.visualViewport.scale, 2, 0.2, + "window.visualViewport.scale reflects pinch-zoom level"); + }, + 'Tester pinch zoomed in correctly', + '5. Scroll fully to the bottom right. Click the continue button ' + + 'there.'); + + addManualTestStep( + function() { + var fullscreenBox = document.getElementById('fullscreenBox'); + var expectedLeft = fullscreenBox.clientWidth / 2; + var expectedTop = fullscreenBox.clientHeight / 2; + var viewOffsetLeft = window.visualViewport.offsetLeft; + var viewOffsetTop = window.visualViewport.offsetTop; + + // This needs to happen before assertions in case they fail. A + // failed assertion stops running this function. + continueBtn.style.position = ""; + continueBtn.style.left = ""; + continueBtn.style.top = ""; + + window.scrollTo(0, 0); + + assert_approx_equals(viewOffsetLeft, expectedLeft, 10, + "OffsetLeft is correct"); + assert_approx_equals(viewOffsetTop, expectedTop, 10, + "OffsetTop"); + }, + 'OffsetLeft and OffsetTop correct when there\'s some layout ' + + 'viewport scrolling as well.', + '6. Pinch-zoom out fully'); + + addManualTestStep( + function() { + continueBtn.remove(); + }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-page-manual.html b/testing/web-platform/tests/visual-viewport/viewport-page-manual.html new file mode 100644 index 0000000000..9fb75ca0a2 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-page-manual.html @@ -0,0 +1,108 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Page</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_done: true, explicit_timeout: true}); + </script> + <style> + html { + width: 100%; + height: 100%; + } + </style> + </head> + <body> + <h1>Viewport: Page</h1> + <h4> + Test Description: Tests the page scrolling properties. + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <h4>Instruction</h4> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + var icbWidth = 0; + var icbHeight = 0; + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + addManualTestStep( + function() {}, + null, + '1. Ensure the browser is at the default pinch and browser zoom ' + + 'levels (100%). Most browsers: ctrl+0'); + + addManualTestStep( + showPinchWidget.bind(null, 1.5, 0, 0, continueTest), + null, + '2.Follow instructions on pinch zoom dialog.'); + + addManualTestStep( + function() { + continueBtn.style.position = "absolute"; + continueBtn.style.left = "400%"; + continueBtn.style.top = "400%"; + + assert_approx_equals(window.visualViewport.scale, 1.5, 0.2, + "window.visualViewport.scale reflects pinch-zoom level"); + }, + 'Tester pinch zoomed in correctly', + '3. Scroll fully to the bottom right. Click the continue button there.'); + + addManualTestStep( + function() { + var expectedLeft = + document.documentElement.clientWidth * 4 + + continueBtn.clientWidth - + window.visualViewport.width; + var expectedTop = + document.documentElement.clientHeight * 4 + + continueBtn.clientHeight - + window.visualViewport.height; + var viewPageLeft = window.visualViewport.pageLeft; + var viewPageTop = window.visualViewport.pageTop; + + // This needs to happen before assertions in case they fail. A + // failed assertion stops running this function. + continueBtn.style.position = ""; + continueBtn.style.left = ""; + continueBtn.style.top = ""; + + window.scrollTo(0, 0); + + assert_approx_equals(viewPageLeft, expectedLeft, 10, + "window.visualViewport.scale reflects pinch-zoom level"); + assert_approx_equals(viewPageTop, expectedTop, 10, + "window.visualViewport.scale reflects pinch-zoom level"); + }, + 'PageLeft and PageTop correct when scrolled', + '4. Pinch-zoom out fully'); + + addManualTestStep( + function() { + continueBtn.remove(); + }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-read-size-causes-layout.html b/testing/web-platform/tests/visual-viewport/viewport-read-size-causes-layout.html new file mode 100644 index 0000000000..0520a7cf80 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-read-size-causes-layout.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<meta name="viewport" content="width=device-width, minimum-scale=1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<style> + html { + height: 100%; + } +</style> + +<h4>This test checks that requesting the viewport size causes any pending layout to occur.</h4> +<script> + async_test(function(t) { + window.onload = t.step_func(function() { + assert_equals(window.visualViewport.width, document.documentElement.clientWidth, + "window.visualViewport.width should match the window width."); + assert_equals(visualViewport.height, document.documentElement.clientHeight, + "window.visualViewport.height should match the window height."); + + // Add overflow so scrollbars appear. + document.body.style.width = "2000px"; + document.body.style.height = "2000px"; + + var viewportWidth = window.visualViewport.width; + var viewportHeight = window.visualViewport.height; + + assert_equals(viewportWidth, document.documentElement.clientWidth, + "Reading viewport width should cause a layout and exclude the new scrollbar."); + assert_equals(viewportHeight, document.documentElement.clientHeight, + "Reading viewport height should cause a layout and exclude the new scrollbar."); + t.done(); + }); + }); +</script> diff --git a/testing/web-platform/tests/visual-viewport/viewport-read-size-in-iframe-causes-layout.html b/testing/web-platform/tests/visual-viewport/viewport-read-size-in-iframe-causes-layout.html new file mode 100644 index 0000000000..a08f7e876f --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-read-size-in-iframe-causes-layout.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<meta name="viewport" content="width=device-width, minimum-scale=1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + iframe { + width: 200px; + height: 300px; + } +</style> + +<h4>This test checks that requesting the viewport size in an iframe causes any pending layout to occur.</h4> +<iframe srcdoc="<!DOCTYPE html><style>html{height:100%}</style>"></iframe> +<script> + async_test(function(t) { + window.onload = t.step_func(function() { + assert_equals(frames[0].window.visualViewport.width, 200, + "Reading width of iframe viewport should match iframe width."); + assert_equals(frames[0].window.visualViewport.height, 300, + "Reading height of iframe viewport should match iframe height."); + + // Add overflow so scrollbars appear. + window.frames[0].window.document.body.style.width = "2000px"; + window.frames[0].window.document.body.style.height = "2000px"; + + var viewportWidth = frames[0].window.visualViewport.width; + var viewportHeight = frames[0].window.visualViewport.height; + + assert_equals(viewportWidth, frames[0].window.document.documentElement.clientWidth, + "Reading width of iframe viewport should cause a layout and exclude the new scrollbar."); + assert_equals(viewportHeight, frames[0].window.document.documentElement.clientHeight, + "Reading height of iframe viewport should cause a layout and exclude the new scrollbar."); + t.done(); + }); + }); +</script> diff --git a/testing/web-platform/tests/visual-viewport/viewport-resize-event-manual.html b/testing/web-platform/tests/visual-viewport/viewport-resize-event-manual.html new file mode 100644 index 0000000000..9088d1589b --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-resize-event-manual.html @@ -0,0 +1,92 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Window Resize Fires Event</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_timeout: true, explicit_done: true}) + </script> + </head> + <body> + <h1>Viewport: Window Resize Fires Event</h1> + <h4> + Test Description: This test checks that a resize event is fired against + the window.visualViewport object when the browser window is resized. + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + var didResizeView; + var cancelable; + var bubbles; + + function resetValues() { + didResizeView = false; + cancelable = undefined; + bubbles = undefined; + } + + addManualTestStep( + function() { + resetValues(); + window.visualViewport.addEventListener('resize', function(e) { + didResizeView = true; + cancelable = e.cancelable; + bubbles = e.bubbles; + }); + }, + null, + '1. Resize the browser window (if on mobile, rotate the device)'); + + + addManualTestStep( + function() { + assert_true(didResizeView); + assert_false(cancelable); + assert_false(bubbles); + }, + 'Resize event fired at window.visualViewport after window resized', + '2. Unrotate the device or reset window size if needed.'); + + addManualTestStep( + resetValues, + null, + '3. Pinch-zoom anywhere on the page by any amount.'); + + addManualTestStep( + function() { + assert_true(didResizeView); + assert_false(cancelable); + assert_false(bubbles); + }, + 'Pinch-zooming fires a resize event', + '4. Pinch-zoom back out'); + + addManualTestStep( + function() { continueBtn.remove(); }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-iframe-show.html b/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-iframe-show.html new file mode 100644 index 0000000000..688148a88f --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-iframe-show.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Resize Event On Showing Iframe</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + async_test(t => { + document.addEventListener("DOMContentLoaded", () => { + let iframe = document.querySelector("iframe"); + onload = () => { + requestAnimationFrame(() => { requestAnimationFrame(() => { + // First full rendering update is complete. + let resize_event_count = 0; + iframe.contentWindow.visualViewport.addEventListener("resize", () => { + resize_event_count++; + }); + iframe.style.display = ""; + iframe.clientWidth; + requestAnimationFrame(() => { + t.step(() => { + assert_equals(resize_event_count, 1); + t.done(); + }); + }) }); // 2x requestAnimationFrame + }) + }; + }); + }, "Resize event fired when an iframe is shown."); + </script> + </head> + <body> + <h1>Viewport: Resize Event On Iframe Size Change</h1> + <h4> + Test Description: This test ensures that we fire a resize event when + an iframe is shown. + </h4> + <iframe style="display: none;" srcdoc="<p>Hello, world!</p>"></iframe> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-iframe-size-change.html b/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-iframe-size-change.html new file mode 100644 index 0000000000..802fee7879 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-iframe-size-change.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Resize Event On Iframe Size Change</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + async_test(t => { + document.addEventListener("DOMContentLoaded", () => { + let iframe = document.querySelector("iframe"); + onload = () => { + requestAnimationFrame(() => { requestAnimationFrame(() => { + // First full rendering update is complete. + let resize_event_count = 0; + iframe.contentWindow.visualViewport.addEventListener("resize", () => { + resize_event_count++; + }); + iframe.style.width = "200px"; + iframe.clientWidth; + requestAnimationFrame(() => { + t.step(() => { + assert_equals(resize_event_count, 1); + t.done(); + }); + }) }); // 2x requestAnimationFrame + }) + }; + }); + }, "Resize event fired when an iframe is resized."); + </script> + </head> + <body> + <h1>Viewport: Resize Event On Iframe Size Change</h1> + <h4> + Test Description: This test ensures that we fire a resize event when + the size of an iframe changes. + </h4> + <iframe srcdoc="<p>Hello, world!</p>"></iframe> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-load-overflowing-page.html b/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-load-overflowing-page.html new file mode 100644 index 0000000000..d5dc1deae7 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-resize-event-on-load-overflowing-page.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Resize Event On Load Overflowing Page</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + var t = async_test( + "Resize event fired exactly once against window.visualViewport if " + + "scrollbars affect layout."); + t.step(() => { + // Run the test in a new window to make sure we don't pick up + // a resize event due to a previous page having a different scale. + var win = window.open("helper-resize-event-on-load-overflowing-page.html"); + t.add_cleanup(() => win.close()); + }); + </script> + </head> + <body> + <h1>Viewport: Resize Event On Load Overflowing Page</h1> + <h4> + Test Description: This test ensures that we fire a resize event against + window.visualViewport if the page has overflow (since this creates a scrollbar + and thus changes the viewport size). + </h4> + <div id="log"></div> + </body> +</html> + diff --git a/testing/web-platform/tests/visual-viewport/viewport-scale-iframe-manual.html b/testing/web-platform/tests/visual-viewport/viewport-scale-iframe-manual.html new file mode 100644 index 0000000000..1c27ab71e1 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-scale-iframe-manual.html @@ -0,0 +1,77 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Scale iframe</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_done: true, explicit_timeout: true}); + </script> + <style> + iframe { + width: 200px; + height: 200px; + } + </style> + </head> + <body> + <h1>Viewport: Scale iframe</h1> + <h4>Test Description: Tests the visualViewport.scale property inside an iframe</h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <p> + <iframe srcdoc="<!DOCTYPE html><style>html {background-color: coral;}</style>"></iframe> + </p> + <div id="log"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + addManualTestStep( + function() {}, + null, + '1. Ensure the browser is at the default pinch and browser zoom ' + + 'levels (100%). Most browsers: ctrl+0'); + + addManualTestStep( + showPinchWidget.bind(null, 2.0, 0, 0, continueTest), + null, + '2.Follow instructions on pinch zoom dialog.'); + + addManualTestStep( + function() { + // Ensure we zoomed in to about what we expect. + assert_approx_equals(window.visualViewport.scale, 2.0, 0.2, + "Main window.visualViewport.scale reflects pinch-zoom level"); + + assert_equals(frames[0].window.visualViewport.scale, 1.0, + "Iframe scale unchanged even when pinch-zoomed"); + }, + 'Check iframe scale is unchanged when page is pinch-zoomed', + '3. Pinch-zoom back out to the minimum scale'); + + addManualTestStep( + function() { + continueBtn.remove(); + }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-scale-manual.html b/testing/web-platform/tests/visual-viewport/viewport-scale-manual.html new file mode 100644 index 0000000000..82bf418e1c --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-scale-manual.html @@ -0,0 +1,81 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Scale</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_done: true, explicit_timeout: true}); + </script> + </head> + <body> + <h1>Viewport: Scale</h1> + <h4>Test Description: Tests the visualViewport.scale property</h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + <div id="spacer"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + addManualTestStep( + function() {}, + null, + '1. Ensure the browser is at the default pinch and browser zoom ' + + 'levels (100%). Most browsers: ctrl+0'); + + addManualTestStep( + showPinchWidget.bind(null, 2.0, 0, 0, continueTest), + null, + '2.Follow instructions on pinch zoom dialog.'); + + addManualTestStep( + function() { + // Ensure we zoomed in to about what we expect. + assert_approx_equals(window.visualViewport.scale, 2.0, 0.2, + "window.visualViewport.scale reflects pinch-zoom level"); + }, + 'With ~200% pinch-zoom', + '3. Pinch-zoom back out to the minimum scale'); + + addManualTestStep( + function() { + assert_equals(window.visualViewport.scale, 1); + }, + 'Fully pinch-zoomed out', + '4. If your browser supports it, browser-zoom in (using ctrl-+). ' + + 'Otherwise just click continue.'); + + addManualTestStep( + function() { + assert_equals(window.visualViewport.scale, 1); + }, + 'Browser zoom doesn\'t change visualViewport.scale', + '5. Reset browser zoom to default (ctrl-0)'); + + addManualTestStep( + function() { + continueBtn.remove(); + }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-scroll-event-manual.html b/testing/web-platform/tests/visual-viewport/viewport-scroll-event-manual.html new file mode 100644 index 0000000000..3fcce10144 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-scroll-event-manual.html @@ -0,0 +1,182 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Scroll Event</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_timeout: true, explicit_done: true}) + </script> + <style> + html { + width: 100%; + height: 100%; + } + </style> + </head> + <body> + <h1>Viewport: Scroll Event</h1> + <h4> + Test Description: This test checks that a scroll event is fired against + the window.visualViewport object when the viewport is scrolled. + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <h4>Instruction</h4> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + var didGetScrollEvent = false; + var cancelable = undefined; + var bubbles = undefined; + + function resetValues() { + didGetScrollEvent = false; + cancelable = undefined; + bubbles = undefined; + } + + addManualTestStep( + function() { + window.visualViewport.addEventListener('scroll', function(e) { + didGetScrollEvent = true; + cancelable = e.cancelable; + bubbles = e.bubbles; + }); + document.documentElement.style.overflow = "hidden"; + }, + null, + '1. Pinch-zoom a little near the "Continue" button but don\'t ' + + 'perform any scrolling.'); + + addManualTestStep( + function() { + requestAnimationFrame(continueTest); + assert_true(didGetScrollEvent, "Got event"); + assert_false(cancelable, "Event is not cancelable"); + assert_false(bubbles, "Event does not bubble"); + }, + 'Got scroll event while pinch-zooming', + ''); + + addManualTestStep( + resetValues, + null, + '2. Scroll in any direction.'); + + addManualTestStep( + function() { + requestAnimationFrame(continueTest); + assert_true(didGetScrollEvent, "Got event"); + assert_false(cancelable, "Event is not cancelable"); + assert_false(bubbles, "Event does not bubble"); + }, + 'Panning viewport fires a scroll event', + ''); + + addManualTestStep( + function() { + continueBtn.style.position = "absolute"; + continueBtn.style.right = "10px"; + continueBtn.style.bottom = "10px"; + }, + null, + '3. Scroll fully to the bottom right and click the continue ' + + 'button.'); + + var offsetLeft; + var offsetTop; + addManualTestStep( + function() { + resetValues(); + document.documentElement.style.overflow = ""; + document.body.style.width = "500%"; + document.body.style.height = "500%"; + continueBtn.style.position = ""; + continueBtn.style.left = ""; + continueBtn.style.top = ""; + + offsetLeft = window.visualViewport.offsetLeft; + offsetTop = window.visualViewport.offsetTop; + + // The visual viewport should be fully scrolled so even if + // scrollTo does normally "push" the layout viewport with the + // visual, there should be no change to either offsetValue + window.scrollTo(10000, 10000); + + requestAnimationFrame(continueTest); + assert_equals(window.visualViewport.offsetLeft, offsetLeft, + "OffsetLeft Unchanged"); + assert_equals(window.visualViewport.offsetTop, offsetTop, + "OffsetTop Unchanged"); + assert_false(didGetScrollEvent, + "Should not get view scroll event"); + }, + 'scrollTo down and right on a fully scrolled visual viewport ' + + 'shouldn\'t change offsets', + ''); + + addManualTestStep( + function() { + requestAnimationFrame(continueTest); + assert_false(didGetScrollEvent, + "Should not get view scroll event"); + resetValues(); + }, + 'scrollTo without changing offsets shouldn\'t fire scroll event ' + + 'on view', + ''); + + addManualTestStep( + function() { + requestAnimationFrame(continueTest); + resetValues(); + window.scrollTo(0, 0); + }, + null, + ''); + + addManualTestStep( + function() { + // How scrollTo behaves in this case isn't fully spec'd but + // make sure it's at least rational if it does change the + // offset values. + var scrollChangedOffset = + offsetLeft != window.visualViewport.offsetLeft || + offsetTop != window.visualViewport.offsetTop; + + document.body.style.width = ""; + document.body.style.height = ""; + + assert_equals(didGetScrollEvent, scrollChangedOffset, + 'If the scrollTo changed offsets it must have fired a ' + + 'scroll event'); + }, + 'scrollTo must fire scroll event if it changes visualViewport.offsetLeft|Top', + '6. Pinch-zoom out fully'); + + addManualTestStep( + function() { continueBtn.remove(); }, + null, + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-scrollbars-cause-resize.html b/testing/web-platform/tests/visual-viewport/viewport-scrollbars-cause-resize.html new file mode 100644 index 0000000000..086e8d92b0 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-scrollbars-cause-resize.html @@ -0,0 +1,74 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Scrollbars Cause Resize</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + </head> + <body> + <h1>Viewport: Scrollbars Cause Resize</h1> + <h4> + Test Description: This test checks that the appearance of classic + scrollbars will cause a resize event to be fired at window.visualViewport. + </h4> + <script> + setup({ explicit_done: true }); + + function runTest() { + var scrollbarThickness = calculateScrollbarThickness(); + + document.documentElement.style.overflow = "hidden"; + var initialWidth = visualViewport.width; + var initialHeight = visualViewport.height; + + test(function() { + assert_equals(window.visualViewport.width, window.innerWidth); + assert_equals(window.visualViewport.height, window.innerHeight); + }, "view size initially matches window size"); + + + var t = async_test( + "Resize event was fired at window.visualViewport if, and only if, " + + "scrollbars are classic (i.e. affect flow)"); + var viewResized = false; + window.visualViewport.addEventListener('resize', function() { + viewResized = true; + }); + + requestAnimationFrame(t.step_func_done(function() { + assert_equals(viewResized, scrollbarThickness > 0); + })); + + document.documentElement.style.overflow = ""; + document.body.style.width = "10000px"; + document.body.style.height = "10000px"; + + var expectedWidth = initialWidth - scrollbarThickness; + var expectedHeight = initialHeight - scrollbarThickness; + + test(function() { + assert_equals(window.visualViewport.width, expectedWidth); + assert_equals(window.visualViewport.height, expectedHeight); + }, "view size reflects appearance of classic scrollbars"); + + + document.body.style.width = ""; + document.body.style.height = ""; + } + + // Run the test after load to make sure any resize from a previous test + // or from the load doesn't interfere. + window.onload = requestAnimationFrame(function() { + try { + runTest(); + } finally { + done(); + } + }); + </script> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-segments.tentative.html b/testing/web-platform/tests/visual-viewport/viewport-segments.tentative.html new file mode 100644 index 0000000000..c90ed29d73 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-segments.tentative.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Viewport Segments: visualViewport.segments tentative</title> +<link rel="help" href="https://wicg.github.io/visual-viewport/"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +"use strict"; + +test(() => { + assert_true('segments' in visualViewport, "`segments` must be a property of visualViewport."); + assert_equals(visualViewport.segments, null, "For a viewport not segmented, no segments must be exposed."); +}); +</script> + diff --git a/testing/web-platform/tests/visual-viewport/viewport-type.html b/testing/web-platform/tests/visual-viewport/viewport-type.html new file mode 100644 index 0000000000..7a9ca425c0 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-type.html @@ -0,0 +1,31 @@ +<!doctype html> +<html> + <head> + <title>Viewport: window.visualViewport type</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>Viewport: window.visualViewport type</h1> + <h4>Test Description: This test checks that window.visualViewport is an object of type VisualViewport.</h4> + <script> + test(function() { + assert_equals(typeof(window.visualViewport), "object"); + }, "window.visualViewport is an object"); + + test(function() { + assert_equals(window.visualViewport.toString(), "[object VisualViewport]"); + }, "window.visualViewport has type `VisualViewport`"); + + addEventListener("load", function() { + document.getElementById("viewtype-log").innerText = typeof(window.visualViewport); + }); + </script> + <div id="complete-notice"> + <p>window.visualViewport is of type: <span id="viewtype-log"></span>.</p> + </div> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-unscaled-scale-iframe.html b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scale-iframe.html new file mode 100644 index 0000000000..30d9bfbe89 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scale-iframe.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Unscaled scale iframe</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <style> + iframe { + width: 200px; + height: 300px; + } + </style> + </head> + <body> + <h1>Viewport: Unscaled scale iframe</h1> + <h4>Test Description: This test checks that the default value for scale inside an iframe is 1.</h4> + <iframe></iframe> + <div id="complete-notice"> + <p>iframe's window.visualViewport.scale is <span id="view-scale-log"></span>.</p> + </div> + <div id="log"></div> + </body> + <script> + test(function() { + assert_equals(frames[0].window.visualViewport.scale, 1); + }, "iframe's visualViewport.scale default value."); + + document.getElementById("view-scale-log").innerText = frames[0].window.visualViewport.scale; + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-unscaled-scale.html b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scale.html new file mode 100644 index 0000000000..b83015d8d1 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scale.html @@ -0,0 +1,26 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Unscaled scale</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + </head> + <body> + <h1>Viewport: Unscaled scale</h1> + <h4>Test Description: This test checks that the default value for scale is 1.</h4> + <div id="complete-notice"> + <p>window.visualViewport.scale is <span id="view-scale-log"></span>.</p> + </div> + <div id="log"></div> + </body> + <script> + test(function() { + assert_equals(window.visualViewport.scale, 1); + }, "visualViewport.scale default value."); + + document.getElementById("view-scale-log").innerText = window.visualViewport.scale; + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-unscaled-scroll-iframe.html b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scroll-iframe.html new file mode 100644 index 0000000000..f9e3023ab7 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scroll-iframe.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Scroll in iframe - no page scale</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <style> + iframe { + width: 200px; + height: 300px; + border: 0; + } + </style> + </head> + <body> + <h1>Viewport: Scroll in iframe - no page scale</h1> + <h4>Test Description: This test checks that window.visualViewport returns correct offset and scroll values without any pinch-zoom page scale applied.</h4> + <iframe></iframe> + <div id="complete-notice"> + <p>frames[0].window.visualViewport's offsetLeft and offsetTop is (<span id="scroll-offset-log"></span>).</p> + <p>frames[0].window.visualViewport's pageLeft and pageTop is (<span id="scroll-page-log"></span>).</p> + </div> + <div id="log"></div> + </body> + <script> + var iframe = frames[0].window; + + // Add overflow we can scroll. + iframe.document.body.style.width = "2000px"; + iframe.document.body.style.height = "2000px"; + + iframe.scrollTo(1000, 1200); + + + test(function() { + assert_equals(iframe.visualViewport.offsetLeft, 0); + }, "offsetLeft must be 0."); + test(function() { + assert_equals(iframe.visualViewport.offsetTop, 0); + }, "offsetTop must be 0."); + test(function() { + assert_equals(iframe.visualViewport.pageLeft, 1000); + }, "pageLeft must reflect location of viewport in document."); + test(function() { + assert_equals(iframe.visualViewport.pageTop, 1200); + }, "pageTop must reflect location of viewport in document."); + + document.getElementById("scroll-offset-log").innerText = iframe.visualViewport.offsetLeft+ ", " + iframe.visualViewport.offsetTop; + document.getElementById("scroll-page-log").innerText = iframe.visualViewport.pageLeft + ", " + iframe.visualViewport.pageTop; + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-unscaled-scroll.html b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scroll.html new file mode 100644 index 0000000000..93623d1962 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-unscaled-scroll.html @@ -0,0 +1,45 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Scroll - no page scale</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + </head> + <body> + <h1>Viewport: Scroll - no page scale</h1> + <h4>Test Description: This test checks that window.visualViewport returns correct offset and scroll values without any pinch-zoom page scale applied.</h4> + <div id="complete-notice"> + <p>window.visualViewport's offsetLeft and offsetTop is (<span id="scroll-offset-log"></span>).</p> + <p>window.visualViewport's pageLeft and pageTop is (<span id="scroll-page-log"></span>).</p> + </div> + <div id="log"></div> + </body> + <script> + // Add overflow we can scroll. + document.body.style.width = "5000px"; + document.body.style.height = "5000px"; + + scrollTo(1000, 1200); + + test(function() { + assert_equals(window.visualViewport.offsetLeft, 0); + }, "offsetLeft must be 0."); + test(function() { + assert_equals(window.visualViewport.offsetTop, 0); + }, "offsetTop must be 0."); + test(function() { + assert_equals(window.visualViewport.pageLeft, 1000); + }, "pageLeft must reflect location of viewport in document."); + test(function() { + assert_equals(window.visualViewport.pageTop, 1200); + }, "pageTop must reflect location of viewport in document."); + + document.getElementById("scroll-offset-log").innerText = window.visualViewport.offsetLeft+ ", " + window.visualViewport.offsetTop; + document.getElementById("scroll-page-log").innerText = window.visualViewport.pageLeft + ", " + window.visualViewport.pageTop; + + scrollTo(0, 0); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-unscaled-size-iframe.html b/testing/web-platform/tests/visual-viewport/viewport-unscaled-size-iframe.html new file mode 100644 index 0000000000..31df6a05fd --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-unscaled-size-iframe.html @@ -0,0 +1,65 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Size in iframe - no page scale</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <style> + iframe { + width: 200px; + height: 300px; + border: 0; + } + </style> + </head> + <body> + <h1>Viewport: Size in iframe - no page scale</h1> + <h4>Test Description: This test checks that window.visualViewport returns correct sizes without any pinch-zoom page scale applied but with scrollbars.</h4> + <iframe></iframe> + <div id="complete-notice"> + <p>frames[0].window.visualViewport width and height is (<span id="size-log"></span>).</p> + <p>frames[0].window.visualViewport width and height when scrollbars are present is (<span id="size-scrollbars-log"></span>).</p> + </div> + <div id="log"></div> + </body> + <script> + setup({ explicit_done: true }); + + function runTest() { + var scrollbarThickness = calculateScrollbarThickness(); + + test(function() { + assert_equals(frames[0].window.visualViewport.width, 200); + }, "window.visualViewport.width of iframe viewport should match iframe width."); + test(function() { + assert_equals(frames[0].window.visualViewport.height, 300); + }, "window.visualViewport.height of iframe viewport should match iframe height."); + + document.getElementById("size-log").innerText = frames[0].window.visualViewport.width + ", " + frames[0].window.visualViewport.height; + + // Add overflow so scrollbars appear. + window.frames[0].window.document.body.style.width = "2000px"; + window.frames[0].window.document.body.style.height = "2000px"; + + test(function() { + assert_equals(frames[0].window.visualViewport.width, 200 - scrollbarThickness); + }, "window.visualViewport.width of iframe viewport should not include scrollbar."); + test(function() { + assert_equals(frames[0].window.visualViewport.height, 300 - scrollbarThickness); + }, "window.visualViewport.height of iframe viewport should not include scrollbar."); + + document.getElementById("size-scrollbars-log").innerText = frames[0].window.visualViewport.width + ", " + frames[0].window.visualViewport.height; + } + + window.onload = function() { + try { + runTest(); + } finally { + done(); + } + } + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-unscaled-size.html b/testing/web-platform/tests/visual-viewport/viewport-unscaled-size.html new file mode 100644 index 0000000000..8ad9fb2cfe --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-unscaled-size.html @@ -0,0 +1,51 @@ +<!doctype html> +<html> + <head> + <title>Viewport: Size unscaled</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <style> + html { + width: 100%; + height: 100%; + } + </style> + </head> + <body> + <h1>Viewport: Size unscaled</h1> + <h4>Test Description: This test checks that window.visualViewport returns correct sizes without any pinch-zoom page scale applied.</h4> + <div id="complete-notice"> + <p>window.visualViewport width and height is (<span id="view-size-log"></span>).</p> + <p>window.visualViewport width and height when scrollbars are present is (<span id="view-size-scrollbar-log"></span>).</p> + </div> + <div id="log"></div> + </body> + <script> + var scrollbarThickness = calculateScrollbarThickness(); + + test(function() { + assert_equals(window.visualViewport.width, document.documentElement.clientWidth); + }, "visualViewport.width should match documentElement.clientWidth when unzoomed."); + test(function() { + assert_equals(window.visualViewport.height, document.documentElement.clientHeight); + }, "visualViewport.height should match documentElement.clientHeight when unzoomed."); + + document.getElementById("view-size-log").innerText = window.visualViewport.width + ", " + window.visualViewport.height; + + // Add overflow so scrollbars appear. + document.body.style.width = "2000px"; + document.body.style.height = "2000px"; + + test(function() { + assert_equals(window.visualViewport.width, document.documentElement.clientWidth); + }, "visualViewport.width should exclude scrollbar."); + test(function() { + assert_equals(window.visualViewport.height, document.documentElement.clientHeight); + }, "visualViewport.height should exclude scrollbar."); + + document.getElementById("view-size-scrollbar-log").innerText = window.visualViewport.width + ", " + window.visualViewport.height; + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport-url-bar-changes-height-manual.html b/testing/web-platform/tests/visual-viewport/viewport-url-bar-changes-height-manual.html new file mode 100644 index 0000000000..563134236b --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport-url-bar-changes-height-manual.html @@ -0,0 +1,87 @@ +<!doctype html> +<html> + <head> + <title>Viewport: URL bar changes height</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="viewport_support.js"></script> + <script> + setup({explicit_timeout: true}); + </script> + <style> + body { + margin-bottom: 1000px; + } + </style> + </head> + <body> + <h1>Viewport: URL bar changes height</h1> + <h4> + Test Description: This test checks that hiding the URL bar correctly + affects the visualViewport height. Skip if the UA doesn't have a URL bar + that hides/shows with scrolling. + </h4> + <h2 style="color: red">THIS IS A MANUAL TEST</h2> + <p id="skip"> + <button id="skipbtn" onclick="skipManualTest();">Skip Test</button> + </p> + <p id="instruction"></p> + <button id="continue">Start Test</button> + <div id="log"></div> + </body> + <script> + var continueBtn = document.getElementById("continue"); + + function continueTest() { + nextStep(function(instructionText) { + var instruction = document.getElementById("instruction"); + continueBtn.innerText = "Continue"; + instruction.innerText = instructionText; + }); + } + + continueBtn.addEventListener('click', continueTest); + + var heights = [ window.visualViewport.height ]; + + addManualTestStep( + function() { + window.visualViewport.addEventListener('resize', function(e) { + heights.push( window.visualViewport.height ); + }); + }, + null, + '1. Scroll down (slowly, e.g. over ~1 sec) so the URL bar hides.'); + + addManualTestStep( + function() { + continueBtn.remove(); + assert_greater_than( + heights.length, 2, 'URL bar caused multiple resize events'); + + var smallest = heights[0]; + var largest = heights[0]; + for (var height in heights) { + if (height < smallest) + smallest = height; + if (height > largest) + largest = height; + } + + var hasIntermediate = false; + for (var height in heights) { + if (height != smallest && height != largest) { + hasIntermediate = true; + break; + } + } + assert_true( + hasIntermediate, + 'Resize fired for intermediate viewport height values'); + }, + 'URL bar updates height continually', + 'Test Complete'); + </script> +</html> diff --git a/testing/web-platform/tests/visual-viewport/viewport_support.js b/testing/web-platform/tests/visual-viewport/viewport_support.js new file mode 100644 index 0000000000..a82bd2b028 --- /dev/null +++ b/testing/web-platform/tests/visual-viewport/viewport_support.js @@ -0,0 +1,180 @@ +// Simulates a small pinch-zoom to provide some page scale to make the visual +// viewport able to differ from the layout viewport. The amount of zoom is +// likely to vary between browsers so tests shouldn't rely on an exact scale +// factor. +// +// Simulates two fingers, 100px apart, pulling apart vertically to 200px of +// separation. +function pinchZoomIn() { + const viewport = window.visualViewport; + const center_x = Math.floor((viewport.width * viewport.scale) / 2); + const center_y = Math.floor((viewport.height * viewport.scale) / 2); + + return new test_driver.Actions() + .setContext(window) + .addPointer("finger1", "touch") + .addPointer("finger2", "touch") + .pointerMove(center_x, center_y-50, {origin: "viewport", sourceName: "finger1"}) + .pointerMove(center_x, center_y+50, {origin: "viewport", sourceName: "finger2"}) + .pointerDown({sourceName: "finger1"}) + .pointerDown({sourceName: "finger2"}) + .pointerMove(center_x, center_y-100, {origin: "viewport", sourceName: "finger1"}) + .pointerMove(center_x, center_y+100, {origin: "viewport", sourceName: "finger2"}) + .pointerUp({sourceName: "finger1"}) + .pointerUp({sourceName: "finger2"}) + .send(); +} + +// If scrollbars affect layout (i.e. what the CSS Overflow spec calls "classic +// scrollbars", as opposed to overlay scrollbars), return the scrollbar +// thickness in CSS pixels. Returns 0 otherwise. +function calculateScrollbarThickness() { + var container = document.createElement("div"); + container.style.width = "100px"; + container.style.height = "100px"; + container.style.position = "absolute"; + container.style.visibility = "hidden"; + container.style.overflow = "auto"; + + document.body.appendChild(container); + + var widthBefore = container.clientWidth; + var longContent = document.createElement("div"); + longContent.style.height = "1000px"; + container.appendChild(longContent); + + var widthAfter = container.clientWidth; + + container.remove(); + + return widthBefore - widthAfter; +} + +// Puts up a widget on screen instructing the user to pinch-zoom in to the +// given scale. The widget is sized such that the given scale is achieved. The +// widget is placed at (x, y) on the page. A button on the widget is used by +// the user to let the widget know that the user has finished. If a callback is +// provided, it will be called when the user dismisses the widget. +function showPinchWidget(scale, x, y, callback) { + var border = 10; + var width = window.innerWidth / scale - border; + var height = window.innerHeight / scale - border; + + var box = document.createElement("div"); + box.style.width = width + "px"; + box.style.height = height + "px"; + + // Adjust the x/y coordinates by the border width. We want the box to + // appear in a place such that if the user gets the window edges exactly on + // the half-point of the border they end up at x/y + box.style.left = x - border/2 + "px"; + box.style.top = y - border/2 + "px"; + + box.style.position = "absolute"; + box.style.backgroundColor = "coral"; + box.style.border = border + "px solid blue"; + box.style.borderBottom = "0"; + box.style.overflow = "auto"; + + var oldDocumentOverflow = document.documentElement.style.overflow; + + var instructions = document.createElement("p"); + instructions.innerText = + "Pinch-zoom and align this box so that the left, right, and top " + + "window edges are over the border on each side. When done, click the " + + "'DONE' button above"; + instructions.style.textAlign = "center"; + instructions.style.fontSize = "medium"; + + var button = document.createElement("button"); + button.innerText = "DONE"; + button.style.width = "50%"; + button.style.height = "20%"; + button.style.fontSize = "medium"; + button.style.marginLeft = "25%"; + button.addEventListener("click", function() { + box.remove(); + document.documentElement.style.overflow = oldDocumentOverflow; + if (callback) + callback(); + }); + + box.appendChild(button); + box.appendChild(instructions); + + document.documentElement.style.overflow = "hidden"; + + document.body.appendChild(box); +} + +// Ends a manual test. Must be called before any async tests are started. +function skipManualTest() { + test(function() { assert_true(false); }, "Manual Test Skipped"); + done(); +} + +var stepInstructions = []; +var testNames = []; +var stepFunctions = []; +var steps; +var curStep = 0; + +// Adds a manual test step to the test. A test will add a series of steps, +// along with instructions. Once all the tests steps are added, the test can +// be run by continually running the nextStep() function. All manual test steps +// must be added before calling nextStep. +// +// |func| A function to be executed at the given step. This function can include +// testharness assertions if |testName| is provided. If this is the last +// step, the |done()| function (used for manual testharness.js tests) +// will be called after |func| is executed. +// |testName| If provided, the |func| will be wrapped in a testharness.js +// async_test with this name. If null, |func| will be executed as a +// free function. +// |instructions| The text to display to the user. Note, these are shown after +// step is executed so these should be instructions to setup the +// checks in the next step. +function addManualTestStep(func, testName, instructions) { + stepFunctions.push(func); + testNames.push(testName); + stepInstructions.push(instructions); +} + +// Runs the next step of the test. This must be called only after all test steps +// have been added using |addManualTestStep|. +// +// |callbackFunc| If provided, will be called with a single argument being the +// instruction string for the current step. Use this to update +// any necessary UI. +function nextStep(callbackFunc) { + if (curStep == 0) + _startManualTest(); + + if (typeof(callbackFunc) === 'function') + callbackFunc(stepInstructions[curStep]); + + steps[curStep](); + curStep++; +} + +function _startManualTest() { + steps = []; + for (let i = 0; i < stepFunctions.length; ++i) { + var stepFunc = stepFunctions[i]; + var testName = testNames[i]; + if (testName) { + steps.push(async_test(testName).step_func(function() { + stepFunctions[i](); + this.done(); + if (i == stepFunctions.length - 1) + done(); + })); + } else { + steps.push(function() { + stepFunctions[i](); + if (i == stepFunctions.length - 1) + done(); + }); + } + } +} |