]> git.ipfire.org Git - thirdparty/foundation/foundation-sites.git/commitdiff
Use pull request #11279 from ncoden/test/fix-interchange-debonce-test-race-condition...
authorNicolas Coden <nicolas@ncoden.fr>
Sat, 16 Jun 2018 08:17:03 +0000 (10:17 +0200)
committerNicolas Coden <nicolas@ncoden.fr>
Sat, 16 Jun 2018 21:02:24 +0000 (23:02 +0200)
2bebd870a feat: add `testInterval` test utility
ad2a282e6 test: wait for debounce for slow browsers in Interval debounce test
33d009a48 docs: add doc for "tryInterval" test utility

Signed-off-by: Nicolas Coden <nicolas@ncoden.fr>
test/javascript/components/interchange.js
test/javascript/index.html
test/javascript/lib/utils.js [new file with mode: 0644]

index 5ef9fd9a357a954cc9a6fa2b42245d43f45423e3..a08b2bca5a372cfb2a539eb8f922bd0dd10f6042 100755 (executable)
@@ -1,4 +1,4 @@
-describe('Interchange', function() {
+describe('Interchange', function () {
   var plugin;
   var $html;
 
@@ -180,9 +180,11 @@ describe('Interchange', function() {
 
       // Trigger several window resize synchrnously and asynchronously.
       // ---
-      // Functions are nested to control when the check is made after the last resize
-      // more precisely (after 10ms). Timeout delays are most often not respected
-      // and the differences between several timeouts running in parrallel can be huge.
+      // Timeout delays are most often not respected and the differences between several
+      // timeouts running in parrallel can be huge. To prevent race conditions we:
+      // * nest timeout in order to make the delay between them more precise
+      // * run the test several time to wait for the debounce, which may be finally
+      //   called way after the expected time.
       setTimeout(function () {
         let spy = sinon.spy(plugin, '_reflow');
         $(window).trigger('resize');
@@ -192,12 +194,18 @@ describe('Interchange', function() {
           $(window).trigger('resize');
           $(window).trigger('resize');
 
-          setTimeout(function () {
-            sinon.assert.calledOnce(spy);
+          tryInterval({
+            interval: debounce,
+            timeout: 1000,
+            try: () => {
+              sinon.assert.calledOnce(spy);
+            },
+            then: () => {
+              $.triggersInitialized = false;
+              done();
+            },
+          });
 
-            $.triggersInitialized = false;
-            done();
-          }, debounce + 1);
         });
       });
     });
index 42c828b938ab1df18e8970d2fce0f2e07628f3c8..9d27a78f2a198761380917ed0d16eb350f4f8bdc 100644 (file)
@@ -21,6 +21,7 @@
       chai.should();
     </script>
     <script src="lib/keyboard-event-mock.js"></script>
+    <script src="lib/utils.js"></script>
     <script src="js-tests.js"></script>
     <script>
       mocha.run();
diff --git a/test/javascript/lib/utils.js b/test/javascript/lib/utils.js
new file mode 100644 (file)
index 0000000..cb0e5aa
--- /dev/null
@@ -0,0 +1,43 @@
+(function (global, $) {
+
+  /**
+  * Try to catch the `do` function every `interval` delay, until it succedes
+  * (does not throw an error) or a given `timout` time passed.
+  * If a `then` function is passed, it is called after `do` succeded.
+  * If a `catch` function is passed, it is called after each time `do` fails.
+  *
+  * @param  {object} opts
+  * @param  {object} opts
+  */
+  global.tryInterval = function (opts) {
+    var _opts = $.extend({}, opts);
+    var totalTime = 0;
+
+    var interval = setInterval(function () {
+      var succeded = false;
+      var error = null;
+
+      totalTime += _opts.time;
+
+      try {
+        _opts.try();
+        succeded = true;
+      }
+      catch (err) { error = err; }
+
+      if (succeded) {
+        clearInterval(interval);
+        if (typeof _opts.then === 'function') _opts.then();
+      }
+      else if (totalTime > _opts.timeout) {
+        clearInterval(interval);
+        throw error;
+      }
+      else {
+        if (typeof _opts.catch === 'function') _opts.catch(error);
+      }
+
+    }, _opts.interval);
+  };
+
+})(window, jQuery);