tests: Change waitFor() to check before first sleep

There are a few problems with sleeping before checking the condition
for the first time:

  * It slows down tests.
  * The predicate is never checked if the interval duration is greater
    than the timeout.
  * 0 can't be used to test if the condition is currently true.

There is a minor disadvantage to sleeping before checking: It will
cause more tests to run without an asynchronous interruption, which
could theoretically mask some async bugs.
This commit is contained in:
Richard Hansen 2020-10-13 22:02:46 -04:00 committed by John McLear
parent 8016bd225f
commit c222fc5d0b
2 changed files with 29 additions and 4 deletions

View file

@ -168,7 +168,7 @@ var helper = {};
return _fail(...args); return _fail(...args);
}; };
var intervalCheck = setInterval(function(){ const check = () => {
try { try {
if (!conditionFunc()) return; if (!conditionFunc()) return;
deferred.resolve(); deferred.resolve();
@ -177,9 +177,11 @@ var helper = {};
} }
clearInterval(intervalCheck); clearInterval(intervalCheck);
clearTimeout(timeout); clearTimeout(timeout);
}, intervalTime); };
var timeout = setTimeout(function(){ const intervalCheck = setInterval(check, intervalTime);
const timeout = setTimeout(() => {
clearInterval(intervalCheck); clearInterval(intervalCheck);
var error = new Error("wait for condition never became true " + conditionFunc.toString()); var error = new Error("wait for condition never became true " + conditionFunc.toString());
deferred.reject(error); deferred.reject(error);
@ -189,8 +191,11 @@ var helper = {};
} }
}, timeoutTime); }, timeoutTime);
// Check right away to avoid an unnecessary sleep if the condition is already true.
check();
return deferred; return deferred;
} };
helper.selectLines = function($startLine, $endLine, startOffset, endOffset){ helper.selectLines = function($startLine, $endLine, startOffset, endOffset){
// if no offset is provided, use beginning of start line and end of end line // if no offset is provided, use beginning of start line and end of end line

View file

@ -193,6 +193,26 @@ describe("the test helper", function(){
},100); },100);
}); });
}); });
describe('checks first then sleeps', function() {
it('resolves quickly if the predicate is immediately true', async function() {
const before = Date.now();
await helper.waitFor(() => true, 1000, 900);
expect(Date.now() - before).to.be.lessThan(800);
});
it('polls exactly once if timeout < interval', async function() {
let calls = 0;
await helper.waitFor(() => { calls++; }, 1, 1000)
.fail(() => {}) // Suppress the redundant uncatchable exception.
.catch(() => {}); // Don't throw an exception -- we know it rejects.
expect(calls).to.be(1);
});
it('resolves if condition is immediately true even if timeout is 0', async function() {
await helper.waitFor(() => true, 0);
});
});
}); });
describe("the selectLines method", function(){ describe("the selectLines method", function(){