DEV: prevents test timeout (#12631)

DEV: prevents test timeout (#12631)

Clock manipulation seems not reliable in component tests. This blog post does a great job of explaining it: Bending Time in Ember Tests - DockYard

Sadly, we don’t have all the “recent” ember test helpers and can’t use things like getSettledState().

For now this pattern seems the most reliable and easy to apply, albeit not great.

Note if you wish to reproduce the current timeout, the following command should do it: QUNIT_SEED=215263717493121190480103670124734840282 rake qunit:test

diff --git a/app/assets/javascripts/discourse/app/components/software-update-prompt.js b/app/assets/javascripts/discourse/app/components/software-update-prompt.js
index c8c91d4..39831fc 100644
--- a/app/assets/javascripts/discourse/app/components/software-update-prompt.js
+++ b/app/assets/javascripts/discourse/app/components/software-update-prompt.js
@@ -1,7 +1,9 @@
 import getURL from "discourse-common/lib/get-url";
-import { later } from "@ember/runloop";
+import { cancel, later } from "@ember/runloop";
 import discourseComputed, { on } from "discourse-common/utils/decorators";
 import Component from "@ember/component";
+import { not } from "@ember/object/computed";
+import { isTesting } from "discourse-common/config/environment";
 
 export default Component.extend({
   showPrompt: false,
@@ -14,9 +16,13 @@ export default Component.extend({
     return getURL("/");
   },
 
+  isHidden: not("showPrompt"),
+
+  _timeoutHandler: null,
+
   @discourseComputed("showPrompt")
   getClassNames(showPrompt) {
-    let classes = ["software-update-prompt"];
+    const classes = ["software-update-prompt"];
 
     if (showPrompt) {
       classes.push("require-software-refresh");
@@ -25,32 +31,36 @@ export default Component.extend({
     return classes.join(" ");
   },
 
-  @discourseComputed("showPrompt")
-  isHidden(showPrompt) {
-    return !showPrompt;
-  },
-
   @on("init")
   initSubscribtions() {
-    let timeout;
-
     this.messageBus.subscribe("/refresh_client", () => {
       this.session.requiresRefresh = true;
     });
 
-    let updatePrompt = this;
     this.messageBus.subscribe("/global/asset-version", (version) => {
       if (this.session.assetVersion !== version) {
         this.session.requiresRefresh = true;
       }
 
-      if (!timeout && this.session.requiresRefresh) {
-        // Since we can do this transparently for people browsing the forum
-        // hold back the message 24 hours.
-        timeout = later(() => {
-          updatePrompt.set("showPrompt", true);
-        }, 1000 * 60 * 24 * 60);
+      if (!this._timeoutHandler && this.session.requiresRefresh) {
+        if (isTesting) {
+          this.set("showPrompt", true);
+        } else {
+          // Since we can do this transparently for people browsing the forum
+          // hold back the message 24 hours.
+          this._timeoutHandler = later(() => {
+            this.set("showPrompt", true);
+          }, 1000 * 60 * 24 * 60);
+        }
       }
     });
   },
+
+  willDestroyElement() {
+    this._super(...arguments);
+
+    this._timeoutHandler && cancel(this._timeoutHandler);
+
+    this._timeoutHandler = null;
+  },
 });
diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js
index 301cfc9..f0bca8a 100644
--- a/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/widgets/software-update-prompt-test.js
@@ -1,30 +1,19 @@
 import componentTest, {
   setupRenderingTest,
 } from "discourse/tests/helpers/component-test";
-import sinon from "sinon";
 import {
   discourseModule,
-  fakeTime,
   publishToMessageBus,
   queryAll,
 } from "discourse/tests/helpers/qunit-helpers";
 import hbs from "htmlbars-inline-precompile";
+import { later } from "@ember/runloop";
 
-let clock = null;
 discourseModule(
   "Integration | Component | software-update-prompt",
   function (hooks) {
     setupRenderingTest(hooks);
 
-    hooks.beforeEach(function () {
-      clock = fakeTime("2019-12-10T08:00:00", "Australia/Brisbane", true);
-    });
-
-    hooks.afterEach(function () {
-      clock.restore();
-      sinon.restore();
-    });
-
     componentTest(
       "software-update-prompt gets correct CSS class after messageBus message",
       {
@@ -36,6 +25,7 @@ discourseModule(
               .length === 0,
             "it does not have the class to show the prompt"
           );
+
           assert.equal(
             queryAll("div.software-update-prompt")[0].getAttribute(
               "aria-hidden"
@@ -46,13 +36,15 @@ discourseModule(
 
           publishToMessageBus("/global/asset-version", "somenewversion");
 
-          clock.tick(1000 * 60 * 24 * 60 + 10);
-
-          assert.ok(
-            queryAll("div.software-update-prompt.require-software-refresh")
-              .length === 1,
-            "it does have the class to show the prompt"
-          );
+          const done = assert.async();
+          later(() => {
+            assert.ok(
+              queryAll("div.software-update-prompt.require-software-refresh")
+                .length === 1,
+              "it does have the class to show the prompt"
+            );
+            done();
+          }, 10);
         },
       }
     );

GitHub sha: 68a032a7

1 Like

This commit appears in #12631 which was approved by CvX. It was merged by jjaffeux.