From 034d00b83ab5b992c59de0be0080947fcb8dd880 Mon Sep 17 00:00:00 2001 From: Wojciech Zawistowski Date: Mon, 7 Oct 2013 17:45:09 +0200 Subject: [PATCH] adds unit tests for Discourse.debouncePromise --- .../discourse/components/debounce.js | 3 +- .../components/debounce_promise_test.js | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 test/javascripts/components/debounce_promise_test.js diff --git a/app/assets/javascripts/discourse/components/debounce.js b/app/assets/javascripts/discourse/components/debounce.js index a4ec880013f..b9be435c6f2 100644 --- a/app/assets/javascripts/discourse/components/debounce.js +++ b/app/assets/javascripts/discourse/components/debounce.js @@ -49,9 +49,10 @@ Discourse.debounce = function(func, wait) { Discourse.debouncePromise = function(func, wait) { var timeout = null; var args = null; + var context = null; return function() { - var context = this; + context = this; var promise = Ember.Deferred.create(); args = arguments; diff --git a/test/javascripts/components/debounce_promise_test.js b/test/javascripts/components/debounce_promise_test.js new file mode 100644 index 00000000000..49822c5ceca --- /dev/null +++ b/test/javascripts/components/debounce_promise_test.js @@ -0,0 +1,91 @@ +var clock, original, debounced, originalPromiseResolvesWith, callback; + +var nothingFired = function(additionalMessage) { + ok(!original.called, "original function is not called " + additionalMessage); + ok(!callback.called, "debounced promise is not resolved " + additionalMessage); +}; + +var originalAndCallbackFiredOnce = function(additionalMessage) { + ok(original.calledOnce, "original function is called once " + additionalMessage); + ok(callback.calledOnce, "debounced promise is resolved once " + additionalMessage); +}; + +module("Discourse.debouncePromise", { + setup: function() { + clock = sinon.useFakeTimers(); + + originalPromiseResolvesWith = null; + original = sinon.spy(function() { + var promise = Ember.Deferred.create(); + promise.resolve(originalPromiseResolvesWith); + return promise; + }); + + debounced = Discourse.debouncePromise(original, 100); + callback = sinon.spy(); + }, + + teardown: function() { + clock.restore(); + } +}); + +test("delays execution till the end of the timeout", function() { + debounced().then(callback); + nothingFired("immediately after calling debounced function"); + + clock.tick(99); + nothingFired("just before the end of the timeout"); + + clock.tick(1); + originalAndCallbackFiredOnce("exactly at the end of the timeout"); +}); + +test("executes only once, no matter how many times debounced function is called during the timeout", function() { + debounced().then(callback); + debounced().then(callback); + + clock.tick(100); + originalAndCallbackFiredOnce("(second call was supressed)"); +}); + +test("does not prolong the timeout when the debounced function is called for the second time during the timeout", function() { + debounced().then(callback); + + clock.tick(50); + debounced().then(callback); + + clock.tick(50); + originalAndCallbackFiredOnce("exactly at the end of the original timeout"); +}); + +test("preserves last call's context and params when executing delayed function", function() { + var firstObj = {}; + var secondObj = {}; + + debounced.call(firstObj, "first"); + debounced.call(secondObj, "second"); + + clock.tick(100); + ok(original.calledOn(secondObj), "the context of the second of two subsequent calls is preserved"); + ok(original.calledWithExactly("second"), "param passed during the second of two subsequent calls is preserved"); +}); + +test("can be called again after timeout passes", function() { + debounced().then(callback); + + clock.tick(100); + debounced().then(callback); + + clock.tick(100); + ok(original.calledTwice, "original function is called for the second time"); + ok(callback.calledTwice, "debounced promise is resolved for the second time"); +}); + +test("passes resolved value from the original promise as a param to the debounced promise's callback", function() { + originalPromiseResolvesWith = "original promise return value"; + debounced().then(callback); + + clock.tick(100); + ok(callback.calledWith("original promise return value")); +});