Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<title>
View transitions: mismatched snapshot containing block size skips transition.
</title>
<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>