DEV: Allow afterFramePaint to be used in tests (#27231)

We need to register a waiter so that `settled()` will wait for `runAfterFramePaint()` callbacks to be run before proceeding.

Re-lands 63b7b598cb, but wrapped with `isTesting()` to avoid production errors.
This commit is contained in:
David Taylor 2024-05-28 17:02:58 +01:00 committed by GitHub
parent 9b11e9a8d1
commit 4dbd072eae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 1 deletions

View File

@ -1,8 +1,18 @@
import DEBUG from "@glimmer/env";
import { registerWaiter } from "@ember/test";
import { isTesting } from "discourse-common/config/environment";
/** /**
* Runs `callback` shortly after the next browser Frame is produced. * Runs `callback` shortly after the next browser Frame is produced.
* ref: https://webperf.tips/tip/measuring-paint-time * ref: https://webperf.tips/tip/measuring-paint-time
*/ */
export default function runAfterFramePaint(callback) { export default function runAfterFramePaint(callback) {
let done = false;
if (DEBUG && isTesting()) {
registerWaiter(() => done);
}
// Queue a "before Render Steps" callback via requestAnimationFrame. // Queue a "before Render Steps" callback via requestAnimationFrame.
requestAnimationFrame(() => { requestAnimationFrame(() => {
// MessageChannel is one of the highest priority task queues // MessageChannel is one of the highest priority task queues
@ -10,7 +20,10 @@ export default function runAfterFramePaint(callback) {
const messageChannel = new MessageChannel(); const messageChannel = new MessageChannel();
// Setup the callback to run in a Task // Setup the callback to run in a Task
messageChannel.port1.onmessage = callback; messageChannel.port1.onmessage = () => {
done = true;
callback();
};
// Queue the Task on the Task Queue // Queue the Task on the Task Queue
messageChannel.port2.postMessage(undefined); messageChannel.port2.postMessage(undefined);

View File

@ -0,0 +1,16 @@
import { settled } from "@ember/test-helpers";
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";
import runAfterFramePaint from "discourse/lib/after-frame-paint";
module("Unit | Lib | afterFramePaint", function (hooks) {
setupTest(hooks);
test("should run callback correctly", async function (assert) {
let callbackDone = false;
runAfterFramePaint(() => (callbackDone = true));
assert.false(callbackDone, "callback was not run immediately");
await settled();
assert.true(callbackDone, "callback was run before settled resolved");
});
});