1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
<!DOCTYPE html>
<title>
View transitions: mismatched snapshot containing block size skips transition.
</title>
<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
<link rel="author" href="mailto:bokan@chromium.org">
<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="/common/utils.js"></script>
<script src="resources/common.js"></script>
<style>
@view-transition {
navigation: auto;
}
::view-transition-group(root) {
animation-duration: 3s;
}
</style>
<script>
const params = new URLSearchParams(location.search);
const is_harness_page = !params.has('popup');
const is_old_page = params.has('popup') && params.get('popup') == 'old';
const is_new_page = params.has('popup') && params.get('popup') == 'new';
const uuid = token();
const popup_old_size = 300;
const popup_new_size = 200;
// This test opens a popup to its own URL but using a param to execute different
// script between the initial "harness" and popup. It then navigates the popup
// to a new page to start a view transition. Popup script is below.
if (is_harness_page) {
// ========= Test Harness Script =============
const popup_old_url = `${location.href.split('?')[0]}?popup=old`;
const popup_new_url = `${location.href.split('?')[0]}?popup=new`;
async function popupEventPromise(event_name) {
return new Promise(resolve => {
addEventListener('message', e => {
if (e.data === event_name)
resolve();
}, {once: true});
});
}
promise_test(async t => {
assertViewTransitionOnNavigationImplemented();
addEventListener('message', e => {
if (e.data.startsWith('FAIL:')) {
const message = e.data.substring(5);
t.step(() => assert_unreached(`Failure in test code: ${message}`));
}
});
let popup = null;
const load_event_in_popup = popupEventPromise('load');
await test_driver.bless('Open a popup in a new window', () => {
const features = `width=${popup_old_size},height=${popup_old_size}`;
popup = window.open(popup_old_url, 'popup', features);
});
await load_event_in_popup;
t.add_cleanup(() => popup.close());
// Pagehide is fired after capturing the outgoing state.
popup.onpagehide = () => popup.resizeTo(popup_new_size, popup_new_size);
// Navigate the popup to the new page and wait for pagereveal.
const pagereveal_in_popup = popupEventPromise('pagereveal');
popup.location = popup_new_url;
await pagereveal_in_popup;
// Ensure the transition is skipped and `ready` rejected.
let did_finish = false;
popup.viewTransition.finished.then(() => { did_finish = true; });
await promise_rejects_dom(t, "InvalidStateError", popup.DOMException,
popup.viewTransition.ready, 'Resize must reject `ready`.');
assert_true(did_finish, "Transition must be skipped by window resize.");
});
} else {
// ========= Popup Script =============
if (is_old_page) {
addEventListener('load', () => window.opener.postMessage('load'));
} else if (is_new_page) {
function errorHandler(e) {
window.opener.postMessage(`FAIL: ${e}`);
}
// Hold rendering until the asynchronous resize from `resizeTo` above has
// been received.
const rendering_blocked_promise = blockRendering();
rendering_blocked_promise.catch(errorHandler);
let rendering_unblocked_promise = null;
const interval_id = setInterval(() => {
// Since rendering is blocked - the resize event isn't fired. The
// innerWidth is also not updated (at least in Chrome) so use the
// outerWidth to wait on the size change. allow a bit of slop in case of
// window decorations.
if (window.outerWidth < popup_new_size + 15) {
rendering_unblocked_promise = unblockRendering();
rendering_unblocked_promise.catch(errorHandler);
clearInterval(interval_id);
}
}, 100);
addEventListener('pagereveal', e => {
// This simply ensures the test only runs if render blocking was
// successful since a fetch failure looks the same as never blocking
// rendering.
Promise.all([rendering_blocked_promise, rendering_unblocked_promise]).then(async () => {
window.viewTransition = e.viewTransition;
window.opener.postMessage('pagereveal');
await Promise.allSettled([e.viewTransition.ready]);
}, () => {});
});
}
}
</script>
|