diff --git a/app/assets/javascripts/discourse/app/lib/after-frame-paint.js b/app/assets/javascripts/discourse/app/lib/after-frame-paint.js index 9105167eaad..aa1cdb4eba2 100644 --- a/app/assets/javascripts/discourse/app/lib/after-frame-paint.js +++ b/app/assets/javascripts/discourse/app/lib/after-frame-paint.js @@ -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. * ref: https://webperf.tips/tip/measuring-paint-time */ export default function runAfterFramePaint(callback) { + let done = false; + + if (DEBUG && isTesting()) { + registerWaiter(() => done); + } + // Queue a "before Render Steps" callback via requestAnimationFrame. requestAnimationFrame(() => { // MessageChannel is one of the highest priority task queues @@ -10,7 +20,10 @@ export default function runAfterFramePaint(callback) { const messageChannel = new MessageChannel(); // 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 messageChannel.port2.postMessage(undefined); diff --git a/app/assets/javascripts/discourse/tests/unit/lib/after-frame-paint-test.js b/app/assets/javascripts/discourse/tests/unit/lib/after-frame-paint-test.js new file mode 100644 index 00000000000..c93696e2a68 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/unit/lib/after-frame-paint-test.js @@ -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"); + }); +});