| <!DOCTYPE HTML> |
| <meta charset=utf-8> |
| <title>Long Animation Frame Timing: first UI Event</title> |
| <meta name="timeout" content="long"> |
| <script src=/resources/testdriver.js></script> |
| <script src=/resources/testdriver-actions.js></script> |
| <script src=/resources/testdriver-vendor.js></script> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="resources/utils.js"></script> |
| |
| <body> |
| <h1>Long Animation Frame: First UI Event</h1> |
| <div id="log"></div> |
| <script> |
| |
| promise_test(async t => { |
| const button = document.createElement("button"); |
| button.innerText = "Click"; |
| document.body.appendChild(button); |
| t.add_cleanup(() => button.remove()); |
| const eventPromise = new Promise(resolve => button.addEventListener("click", event => { |
| busy_wait(); |
| resolve(event); |
| })); |
| const entryPromise = expect_long_frame_with_script(() => { |
| test_driver.click(button); |
| }, s => s.name === "BUTTON.onclick", t); |
| await new Promise(resolve => t.step_timeout(resolve, 0)); |
| const event = await eventPromise; |
| const [entry] = await entryPromise; |
| assert_equals(entry.firstUIEventTimestamp, event.timeStamp); |
| }, "LoAF should expose firstUIEventTimestamp for click events"); |
| |
| promise_test(async t => { |
| const button = document.createElement("button"); |
| button.innerText = "Hover"; |
| document.body.appendChild(button); |
| t.add_cleanup(() => button.remove()); |
| let expectedTimestamp = null; |
| const entryPromise = expect_long_frame_with_script(async () => { |
| const eventPromise = new Promise(resolve => button.addEventListener("pointermove", event => { |
| busy_wait(); |
| expectedTimestamp = event.timeStamp; |
| resolve(); |
| })); |
| |
| const actions = new test_driver.Actions() |
| .pointerMove(0, 0, {origin: button}) |
| .pointerDown() |
| .pointerUp(); |
| await actions.send(); |
| await eventPromise; |
| }, s => s.name === "BUTTON.onpointermove", t); |
| const [entry] = await entryPromise; |
| assert_equals(entry.firstUIEventTimestamp, expectedTimestamp); |
| }, "LoAF should expose firstUIEventTimestamp for pointermove events"); |
| |
| promise_test(async t => { |
| const button = document.createElement("button"); |
| button.innerText = "Click"; |
| document.body.appendChild(button); |
| t.add_cleanup(() => button.remove()); |
| let firstUIEventTimestamp = null; |
| const eventPromise = new Promise(resolve => button.addEventListener("click", event => { |
| if (firstUIEventTimestamp) |
| resolve(event); |
| else { |
| firstUIEventTimestamp = event.timeStamp; |
| busy_wait(); |
| } |
| })); |
| const entryPromise = expect_long_frame_with_script(() => { |
| test_driver.click(button); |
| test_driver.click(button); |
| }, s => s.name === "BUTTON.onclick", t); |
| const [event, [entry]] = await Promise.all([eventPromise, entryPromise]); |
| assert_equals(entry.firstUIEventTimestamp, firstUIEventTimestamp); |
| }, "firstUIEventTimestamp doesn't have to come from a long script"); |
| |
| |
| promise_test(async t => { |
| const entryPromise = expect_long_frame_with_script(() => { |
| const img = document.createElement("img"); |
| img.src = "/images/green.png"; |
| const promise = new Promise(resolve => |
| img.addEventListener("load", event => { |
| busy_wait(); |
| resolve(); |
| })); |
| document.body.appendChild(img); |
| t.add_cleanup(() => img.remove()); |
| return promise; |
| }, s => s.name === "IMG[src=/images/green.png].onload", t); |
| |
| const [entry] = await entryPromise; |
| assert_equals(entry.firstUIEventTimestamp, 0); |
| }, "Non-UI events don't affect firstUIEventTimestamp"); |
| |
| </script> |
| </body> |