From 4dbd072eaeccb9211f3e5dcd69876b042ad59b28 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Tue, 28 May 2024 17:02:58 +0100 Subject: [PATCH] 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 63b7b598cb9cd93e90e447fea24f2f517c2592c5, but wrapped with `isTesting()` to avoid production errors. --- .../discourse/app/lib/after-frame-paint.js | 15 ++++++++++++++- .../tests/unit/lib/after-frame-paint-test.js | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/discourse/tests/unit/lib/after-frame-paint-test.js 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"); + }); +});