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