From 4d5d1984cb8132c5f73ff020b261c1bc8724b771 Mon Sep 17 00:00:00 2001 From: Ognjen Jevremovic Date: Sat, 6 Mar 2021 20:18:32 +0100 Subject: [PATCH 1/2] =?UTF-8?q?test:=20=F0=9F=92=8D=20Time=20tampering=20t?= =?UTF-8?q?ests=20for=20=5F.throttle=20and=20=5F.deobounce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Monkey patch `Date.prototype` getTime and valueOf methods and `Date.now` method in _.debounce and _.throttle test cases. Provide additional test case asserting the outputs before and after monkey patching. Remove the reference to _.now method in test cases as the underlying implementation of library methods don't reference the methods from the `_` object but rather call dependent methods directly. ✅ Closes: #2883 --- test/functions.js | 116 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 14 deletions(-) diff --git a/test/functions.js b/test/functions.js index 0ddfeb66c..d4584c782 100644 --- a/test/functions.js +++ b/test/functions.js @@ -390,22 +390,66 @@ var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 100); - var origNowFunc = _.now; + var originalNowFunc = Date.now; + var originalGetTimeFunc = Date.prototype.getTime; throttledIncr(); - assert.strictEqual(counter, 1); - _.now = function() { - return new Date(2013, 0, 1, 1, 1, 1); - }; + assert.strictEqual(counter, 1, '_.throttle: incr was called immediately'); + + Date.prototype.getTime = function() { + return +(new Date(2013, 0, 1, 1, 1, 1)); + } + Date.now = function() { + return +(new Date(2013, 0, 1, 1, 1, 1)); + } _.delay(function() { throttledIncr(); - assert.strictEqual(counter, 2); + assert.strictEqual(counter, 2, '_.throttle: incr was called successfully, with tampered system time'); done(); - _.now = origNowFunc; + Date.now = originalNowFunc; + Date.prototype.getTime = originalGetTimeFunc; }, 200); }); + QUnit.test('throttle continues to function after system time is not accessible (or in invalid format)', function(assert) { + assert.expect(3); + var done = assert.async(); + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + var originalNowFunc = Date.now; + var originalGetTimeFunc = Date.prototype.getTime; + var originalValueOfFunc = Date.prototype.valueOf; + + throttledIncr(); + assert.strictEqual(counter, 1, '_.throttle: incr was called immediately'); + + Date.prototype.valueOf = function() { + return null; + } + Date.prototype.getTime = function() { + return null; + } + Date.now = function() { + return null; + } + + _.delay(function() { + throttledIncr(); + assert.strictEqual(counter, 2, '_.throttle: incr was debounced successfully, with tampered system time'); + Date.now = originalNowFunc; + Date.prototype.getTime = originalGetTimeFunc; + Date.prototype.valueOf = originalValueOfFunc; + }, 200); + + _.delay(function() { + throttledIncr(); + assert.strictEqual(counter, 3, '_.throttle: incr was debounced successfully, after system time method restoration'); + done(); + }, 400); + }); + QUnit.test('throttle re-entrant', function(assert) { assert.expect(2); var done = assert.async(); @@ -542,24 +586,68 @@ assert.expect(2); var done = assert.async(); var counter = 0; - var origNowFunc = _.now; var debouncedIncr = _.debounce(function(){ counter++; }, 100, true); + var originalNowFunc = Date.now; + var originalGetTimeFunc = Date.prototype.getTime; debouncedIncr(); - assert.strictEqual(counter, 1, 'incr was called immediately'); + assert.strictEqual(counter, 1, '_.debounce: incr was called immediately'); - _.now = function() { - return new Date(2013, 0, 1, 1, 1, 1); - }; + Date.prototype.getTime = function() { + return +(new Date(2013, 0, 1, 1, 1, 1)); + } + Date.now = function() { + return +(new Date(2013, 0, 1, 1, 1, 1)); + } _.delay(function() { debouncedIncr(); - assert.strictEqual(counter, 2, 'incr was debounced successfully'); + assert.strictEqual(counter, 2, '_.debounce: incr was debounced successfully, with tampered system time'); done(); - _.now = origNowFunc; + Date.now = originalNowFunc; + Date.prototype.getTime = originalGetTimeFunc; + }, 200); + }); + + QUnit.test('debounce after system time is is not accessible (or in invalid format)', function(assert) { + assert.expect(3); + var done = assert.async(); + var counter = 0; + var debouncedIncr = _.debounce(function(){ + counter++; + }, 100, true); + var originalNowFunc = Date.now; + var originalGetTimeFunc = Date.prototype.getTime; + var originalValueOfFunc = Date.prototype.valueOf; + + debouncedIncr(); + assert.strictEqual(counter, 1, '_.debounce: incr was called immediately'); + + Date.prototype.valueOf = function() { + return null; + }; + Date.prototype.getTime = function() { + return null; + }; + Date.now = function() { + return null; + }; + + _.delay(function() { + debouncedIncr(); + assert.strictEqual(counter, 2, '_.debounce: incr was debounced successfully, with tampered system time'); + Date.now = originalNowFunc; + Date.prototype.getTime = originalGetTimeFunc; + Date.prototype.valueOf = originalValueOfFunc; }, 200); + + _.delay(function() { + debouncedIncr(); + assert.strictEqual(counter, 3, '_.debounce: incr was debounced successfully, after system time method restoration'); + done(); + }, 400); }); QUnit.test('debounce re-entrant', function(assert) { From 3a5c878f41575300fa9f6afb12ea314cfa245d57 Mon Sep 17 00:00:00 2001 From: Ognjen Jevremovic Date: Mon, 8 Mar 2021 10:31:27 +0100 Subject: [PATCH 2/2] test: Assertion comment updates; `_.throttle` and `_.debounce`. Update the assertion comments in `_.throttle` and `_.debounce` unit tests, in order to prevent confusion and add more brevity to the test case messages. --- test/functions.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/functions.js b/test/functions.js index d4584c782..20144179a 100644 --- a/test/functions.js +++ b/test/functions.js @@ -394,7 +394,7 @@ var originalGetTimeFunc = Date.prototype.getTime; throttledIncr(); - assert.strictEqual(counter, 1, '_.throttle: incr was called immediately'); + assert.strictEqual(counter, 1, 'incr was called immediately'); Date.prototype.getTime = function() { return +(new Date(2013, 0, 1, 1, 1, 1)); @@ -405,7 +405,7 @@ _.delay(function() { throttledIncr(); - assert.strictEqual(counter, 2, '_.throttle: incr was called successfully, with tampered system time'); + assert.strictEqual(counter, 2, 'incr was throttled successfully, with tampered system time'); done(); Date.now = originalNowFunc; Date.prototype.getTime = originalGetTimeFunc; @@ -423,7 +423,7 @@ var originalValueOfFunc = Date.prototype.valueOf; throttledIncr(); - assert.strictEqual(counter, 1, '_.throttle: incr was called immediately'); + assert.strictEqual(counter, 1, 'incr was called immediately'); Date.prototype.valueOf = function() { return null; @@ -437,7 +437,7 @@ _.delay(function() { throttledIncr(); - assert.strictEqual(counter, 2, '_.throttle: incr was debounced successfully, with tampered system time'); + assert.strictEqual(counter, 2, 'incr was throttled successfully, with tampered system time'); Date.now = originalNowFunc; Date.prototype.getTime = originalGetTimeFunc; Date.prototype.valueOf = originalValueOfFunc; @@ -445,7 +445,7 @@ _.delay(function() { throttledIncr(); - assert.strictEqual(counter, 3, '_.throttle: incr was debounced successfully, after system time method restoration'); + assert.strictEqual(counter, 3, 'incr was throttled successfully, after system time method restoration'); done(); }, 400); }); @@ -593,7 +593,7 @@ var originalGetTimeFunc = Date.prototype.getTime; debouncedIncr(); - assert.strictEqual(counter, 1, '_.debounce: incr was called immediately'); + assert.strictEqual(counter, 1, 'incr was called immediately'); Date.prototype.getTime = function() { return +(new Date(2013, 0, 1, 1, 1, 1)); @@ -604,7 +604,7 @@ _.delay(function() { debouncedIncr(); - assert.strictEqual(counter, 2, '_.debounce: incr was debounced successfully, with tampered system time'); + assert.strictEqual(counter, 2, 'incr was debounced successfully, with tampered system time'); done(); Date.now = originalNowFunc; Date.prototype.getTime = originalGetTimeFunc; @@ -623,7 +623,7 @@ var originalValueOfFunc = Date.prototype.valueOf; debouncedIncr(); - assert.strictEqual(counter, 1, '_.debounce: incr was called immediately'); + assert.strictEqual(counter, 1, 'incr was called immediately'); Date.prototype.valueOf = function() { return null; @@ -637,7 +637,7 @@ _.delay(function() { debouncedIncr(); - assert.strictEqual(counter, 2, '_.debounce: incr was debounced successfully, with tampered system time'); + assert.strictEqual(counter, 2, 'incr was debounced successfully, with tampered system time'); Date.now = originalNowFunc; Date.prototype.getTime = originalGetTimeFunc; Date.prototype.valueOf = originalValueOfFunc; @@ -645,7 +645,7 @@ _.delay(function() { debouncedIncr(); - assert.strictEqual(counter, 3, '_.debounce: incr was debounced successfully, after system time method restoration'); + assert.strictEqual(counter, 3, 'incr was debounced successfully, after system time method restoration'); done(); }, 400); });