Waiting for an event in layout test...
I’m gonna give you a game changing function: function listenForEventOnce(target, name, timeout) { return new Promise((resolve, reject) => { const timer = timeout ? setTimeout(reject, timeout) : null; target.addEventListener(name, () => { if (timer) clearTimeout(timer); resolve(); }, {once: true}); }); } You can then write a test like this: await listenForEventOnce(document.body, 'load'); // do stuff after load event. await listenForEventOnce(document.querySelector('input'), 'focus'); await listenForEventOnce(visualViewport, 'scroll', 5000); // After the input element is focused, then the visual viewport scrolled or 5 seconds has passed. - R. Niwa
On May 30, 2019, at 11:01 PM, Ryosuke Niwa <rniwa@webkit.org> wrote:
I’m gonna give you a game changing function:
function listenForEventOnce(target, name, timeout) { return new Promise((resolve, reject) => { const timer = timeout ? setTimeout(reject, timeout) : null; target.addEventListener(name, () => { if (timer) clearTimeout(timer); resolve(); }, {once: true}); }); }
You can then write a test like this: await listenForEventOnce(document.body, 'load'); // do stuff after load event.
await listenForEventOnce(document.querySelector('input'), 'focus'); await listenForEventOnce(visualViewport, 'scroll', 5000); // After the input element is focused, then the visual viewport scrolled or 5 seconds has passed.
Ryosuke++. Just FYI, if you’re writing LayoutTests, we’ve got something very similar in LayoutTests/media/video-test.js: function waitFor(element, type) { return new Promise(resolve => { element.addEventListener(type, event => { consoleWrite(`EVENT(${event.type})`); resolve(event); }, { once: true }); }); } And: function sleepFor(duration) { return new Promise(resolve => { setTimeout(resolve, duration); }); } And also: function shouldReject(promise) { return new Promise((resolve, reject) => { promise.then(result => { logResult(Failed, 'Promise resolved incorrectly'); reject(result); }).catch((error) => { logResult(Success, 'Promise rejected correctly'); resolve(error); }); }); } So you could also do: await Promise.race(waitFor(document.body, ‘load’), shouldReject(sleepFor(5000))); Although we’d probably want a new function, “rejectIn(duration)”, and then it’d be: await shouldResolve(Promise.race(waitFor(document.body, ‘load’), rejectIn(5000))); But all that said, I agree that wrapping events in Promises makes it very easy to write readable, single `async` function test cases. A+++, would write test again. -Jer
- R. Niwa
_______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-dev
participants (2)
-
Jer Noble
-
Ryosuke Niwa