|  | <!DOCTYPE html> | 
|  | <html> | 
|  | <title>View transitions: ensure input targets document root while rendering is suppressed</title> | 
|  | <link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/"> | 
|  | <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7797"> | 
|  | <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-actions.js"></script> | 
|  | <script src="/resources/testdriver-vendor.js"></script> | 
|  |  | 
|  | <style> | 
|  | :root { | 
|  | /* Ensure clicks during the transition fall through the pseudo tree root to | 
|  | * real DOM */ | 
|  | view-transition-name: none; | 
|  | } | 
|  |  | 
|  | ::view-transition { | 
|  | /* Ensure clicks during the transition fall through the pseudo tree root to | 
|  | * real DOM */ | 
|  | pointer-events: none; | 
|  | width: 0; | 
|  | height: 0; | 
|  | } | 
|  |  | 
|  | ::view-transition-group(*) { | 
|  | animation-duration: 30s; | 
|  | } | 
|  |  | 
|  | #clicktarget { | 
|  | width: 100px; | 
|  | height: 100px; | 
|  | background: red; | 
|  | } | 
|  |  | 
|  | #transition { | 
|  | width: 100px; | 
|  | height: 100px; | 
|  | background: blue; | 
|  | contain: paint; | 
|  | view-transition-name: transitionElement; | 
|  | } | 
|  | </style> | 
|  |  | 
|  | <div id="clicktarget"></div> | 
|  | <div id="transition"></div> | 
|  |  | 
|  | <script> | 
|  | const target = document.getElementById("clicktarget"); | 
|  |  | 
|  | async function sendAndWaitForClick() { | 
|  | return new Promise(async (resolve) => { | 
|  |  | 
|  | function eventHandler(ev) { | 
|  | resolve(ev); | 
|  | } | 
|  |  | 
|  | document.documentElement.addEventListener("click", eventHandler); | 
|  |  | 
|  | await new test_driver.Actions() | 
|  | .setContext(window) | 
|  | .addPointer("mousePointer1", "mouse") | 
|  | .pointerMove(10, 10, {origin: 'viewport', sourceName: "mousePointer1"}) | 
|  | .pointerDown({sourceName: "mousePointer1"}) | 
|  | .pointerUp({sourceName: "mousePointer1"}) | 
|  | .send(); | 
|  |  | 
|  | document.documentElement.removeEventListener("click", eventHandler); | 
|  | }); | 
|  | } | 
|  |  | 
|  | promise_test(async t => { | 
|  | assert_implements(document.startViewTransition, "Missing document.startViewTransition"); | 
|  | assert_not_equals(target, null, "PRECONDITION: target element is valid"); | 
|  |  | 
|  | // Ensure input is initialized before blocking rendering. | 
|  | await new test_driver.Actions() | 
|  | .setContext(window) | 
|  | .addPointer("mousePointer1", "mouse") | 
|  | .pointerMove(0, 0, {origin: "viewport", sourceName: "mousePointer1"}) | 
|  | .send(); | 
|  |  | 
|  | let clickEvent = null; | 
|  |  | 
|  | let transition = document.startViewTransition(async () => { | 
|  | clickEvent = await sendAndWaitForClick(); | 
|  | }); | 
|  |  | 
|  | await transition.ready; | 
|  |  | 
|  | assert_equals(clickEvent.target, document.documentElement, | 
|  | "Events must target the transition root while render blocked"); | 
|  | clickEvent = null; | 
|  |  | 
|  | clickEvent = await sendAndWaitForClick(); | 
|  |  | 
|  | // This just ensures we're not passing the above check by accident. | 
|  | assert_equals(clickEvent.target, target, | 
|  | "During transition, event should hit real DOM"); | 
|  |  | 
|  | }, "Input when rendering suppressed targets root"); | 
|  | </script> |