Treat any argument to the done callback as an error

This reduces the risk of incorrectly passing a spec due to not correctly
detecting that an argument is an `Error` instance. Detecting Error instances
in a way that's reliable and portable across different browsers, TrustedTypes,
and frames is difficult.

[Finishes #178267587]
This commit is contained in:
Steve Gravrock
2021-07-24 09:30:39 -07:00
parent 6f04044417
commit 0170005015
3 changed files with 23 additions and 113 deletions

View File

@@ -7491,17 +7491,11 @@ getJasmineRequireObj().QueueRunner = function(j$) {
next = once(function next(err) { next = once(function next(err) {
cleanup(); cleanup();
if (j$.isError_(err)) { if (typeof err !== 'undefined') {
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) { if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
self.fail(err); self.fail(err);
} }
self.errored = errored = true; self.errored = errored = true;
} else if (typeof err !== 'undefined' && !self.errored) {
self.deprecated(
'Any argument passed to a done callback will be treated as an ' +
'error in a future release. Call the done callback without ' +
"arguments if you don't want to trigger a spec failure."
);
} }
function runNext() { function runNext() {

View File

@@ -150,109 +150,31 @@ describe('QueueRunner', function() {
}); });
describe('When next is called with an argument', function() { describe('When next is called with an argument', function() {
describe('that is an Error', function() { it('explicitly fails and moves to the next function', function() {
it('explicitly fails and moves to the next function', function() { var err = 'anything except undefined',
var err = new Error('foo'), queueableFn1 = {
queueableFn1 = { fn: function(done) {
fn: function(done) { setTimeout(function() {
setTimeout(function() { done(err);
done(err); }, 100);
}, 100); }
} },
}, queueableFn2 = { fn: jasmine.createSpy('fn2') },
queueableFn2 = { fn: jasmine.createSpy('fn2') }, failFn = jasmine.createSpy('fail'),
failFn = jasmine.createSpy('fail'), queueRunner = new jasmineUnderTest.QueueRunner({
queueRunner = new jasmineUnderTest.QueueRunner({ queueableFns: [queueableFn1, queueableFn2],
queueableFns: [queueableFn1, queueableFn2], fail: failFn
fail: failFn });
});
queueRunner.execute(); queueRunner.execute();
expect(failFn).not.toHaveBeenCalled(); expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled(); expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100); jasmine.clock().tick(100);
expect(failFn).toHaveBeenCalledWith(err); expect(failFn).toHaveBeenCalledWith(err);
expect(queueableFn2.fn).toHaveBeenCalled(); expect(queueableFn2.fn).toHaveBeenCalled();
});
it('does not log a deprecation', function() {
var err = new Error('foo'),
queueableFn1 = {
fn: function(done) {
setTimeout(function() {
done(err);
}, 100);
}
},
deprecated = jasmine.createSpy('deprecated'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1],
deprecated: deprecated
});
queueRunner.execute();
jasmine.clock().tick(100);
expect(deprecated).not.toHaveBeenCalled();
});
});
describe('that is not an Error', function() {
it('logs a deprecation', function() {
var queueableFn1 = {
fn: function(done) {
setTimeout(function() {
done('not an Error');
}, 100);
}
},
deprecated = jasmine.createSpy('deprecated'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1],
deprecated: deprecated
});
queueRunner.execute();
jasmine.clock().tick(100);
expect(deprecated).toHaveBeenCalledWith(
'Any argument passed to a done callback will be treated as an ' +
'error in a future release. Call the done callback without ' +
"arguments if you don't want to trigger a spec failure."
);
});
it('moves to the next function without failing', function() {
var queueableFn1 = {
fn: function(done) {
setTimeout(function() {
done('not an Error');
}, 100);
}
},
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
fail: failFn,
deprecated: function() {}
});
queueRunner.execute();
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100);
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).toHaveBeenCalled();
});
}); });
}); });

View File

@@ -100,17 +100,11 @@ getJasmineRequireObj().QueueRunner = function(j$) {
next = once(function next(err) { next = once(function next(err) {
cleanup(); cleanup();
if (j$.isError_(err)) { if (typeof err !== 'undefined') {
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) { if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
self.fail(err); self.fail(err);
} }
self.errored = errored = true; self.errored = errored = true;
} else if (typeof err !== 'undefined' && !self.errored) {
self.deprecated(
'Any argument passed to a done callback will be treated as an ' +
'error in a future release. Call the done callback without ' +
"arguments if you don't want to trigger a spec failure."
);
} }
function runNext() { function runNext() {