Start breaking up integration/EnvSpec.js
This commit is contained in:
@@ -429,350 +429,6 @@ describe('Env integration', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Handling async errors', function() {
|
|
||||||
it('routes async errors to a running spec', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn, delay) {
|
|
||||||
clearTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
const reporter = jasmine.createSpyObj('fakeReporter', [
|
|
||||||
'specDone',
|
|
||||||
'suiteDone'
|
|
||||||
]);
|
|
||||||
|
|
||||||
env.addReporter(reporter);
|
|
||||||
|
|
||||||
env.describe('A suite', function() {
|
|
||||||
env.it('fails', function(specDone) {
|
|
||||||
setTimeout(function() {
|
|
||||||
dispatchErrorEvent(global, { error: 'fail' });
|
|
||||||
specDone();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
expect(reporter.specDone).toHaveFailedExpectationsForRunnable(
|
|
||||||
'A suite fails',
|
|
||||||
['fail thrown']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When the running spec has reported specDone', function() {
|
|
||||||
it('routes async errors to an ancestor suite', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn) {
|
|
||||||
clearTimeout(fn);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
|
|
||||||
const realClearStack = jasmineUnderTest.getClearStack(global);
|
|
||||||
const clearStackCallbacks = {};
|
|
||||||
let clearStackCallCount = 0;
|
|
||||||
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
|
|
||||||
clearStackCallCount++;
|
|
||||||
|
|
||||||
if (clearStackCallbacks[clearStackCallCount]) {
|
|
||||||
clearStackCallbacks[clearStackCallCount]();
|
|
||||||
}
|
|
||||||
|
|
||||||
realClearStack(fn);
|
|
||||||
});
|
|
||||||
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
|
|
||||||
let suiteErrors = [];
|
|
||||||
env.addReporter({
|
|
||||||
suiteDone: function(result) {
|
|
||||||
const messages = result.failedExpectations.map(e => e.message);
|
|
||||||
suiteErrors = suiteErrors.concat(messages);
|
|
||||||
},
|
|
||||||
specDone: function() {
|
|
||||||
clearStackCallbacks[clearStackCallCount + 1] = function() {
|
|
||||||
dispatchErrorEvent(global, {
|
|
||||||
error: 'fail at the end of the reporter queue'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
clearStackCallbacks[clearStackCallCount + 2] = function() {
|
|
||||||
dispatchErrorEvent(global, {
|
|
||||||
error: 'fail at the end of the spec queue'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('A suite', function() {
|
|
||||||
env.it('is finishing when the failure occurs', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
expect(suiteErrors).toEqual([
|
|
||||||
'fail at the end of the reporter queue thrown',
|
|
||||||
'fail at the end of the spec queue thrown'
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('routes async errors to a running suite', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn, delay) {
|
|
||||||
clearTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
const reporter = jasmine.createSpyObj('fakeReporter', [
|
|
||||||
'specDone',
|
|
||||||
'suiteDone'
|
|
||||||
]);
|
|
||||||
|
|
||||||
env.addReporter(reporter);
|
|
||||||
|
|
||||||
env.fdescribe('A suite', function() {
|
|
||||||
env.it('fails', function(specDone) {
|
|
||||||
setTimeout(function() {
|
|
||||||
specDone();
|
|
||||||
queueMicrotask(function() {
|
|
||||||
queueMicrotask(function() {
|
|
||||||
dispatchErrorEvent(global, { error: 'fail' });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('Ignored', function() {
|
|
||||||
env.it('is not run', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
expect(reporter.specDone).not.toHaveFailedExpectationsForRunnable(
|
|
||||||
'A suite fails',
|
|
||||||
['fail thrown']
|
|
||||||
);
|
|
||||||
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable(
|
|
||||||
'A suite',
|
|
||||||
['fail thrown']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When the running suite has reported suiteDone', function() {
|
|
||||||
it('routes async errors to an ancestor suite', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn, delay) {
|
|
||||||
clearTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
|
|
||||||
const realClearStack = jasmineUnderTest.getClearStack(global);
|
|
||||||
const clearStackCallbacks = {};
|
|
||||||
let clearStackCallCount = 0;
|
|
||||||
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
|
|
||||||
clearStackCallCount++;
|
|
||||||
|
|
||||||
if (clearStackCallbacks[clearStackCallCount]) {
|
|
||||||
clearStackCallbacks[clearStackCallCount]();
|
|
||||||
}
|
|
||||||
|
|
||||||
realClearStack(fn);
|
|
||||||
});
|
|
||||||
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
|
|
||||||
let suiteErrors = [];
|
|
||||||
env.addReporter({
|
|
||||||
suiteDone: function(result) {
|
|
||||||
const messages = result.failedExpectations.map(e => e.message);
|
|
||||||
suiteErrors = suiteErrors.concat(messages);
|
|
||||||
|
|
||||||
if (result.description === 'A nested suite') {
|
|
||||||
clearStackCallbacks[clearStackCallCount + 1] = function() {
|
|
||||||
dispatchErrorEvent(global, {
|
|
||||||
error: 'fail at the end of the reporter queue'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
clearStackCallbacks[clearStackCallCount + 2] = function() {
|
|
||||||
dispatchErrorEvent(global, {
|
|
||||||
error: 'fail at the end of the suite queue'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('A suite', function() {
|
|
||||||
env.describe('A nested suite', function() {
|
|
||||||
env.it('a spec', function() {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
expect(suiteErrors).toEqual([
|
|
||||||
'fail at the end of the reporter queue thrown',
|
|
||||||
'fail at the end of the suite queue thrown'
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('When the env has started reporting jasmineDone', function() {
|
|
||||||
it('logs the error to the console', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn, delay) {
|
|
||||||
clearTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
|
|
||||||
spyOn(console, 'error');
|
|
||||||
|
|
||||||
env.addReporter({
|
|
||||||
jasmineDone: function() {
|
|
||||||
dispatchErrorEvent(global, { error: 'a very late error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('a spec', function() {});
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
/* eslint-disable-next-line no-console */
|
|
||||||
expect(console.error).toHaveBeenCalledWith(
|
|
||||||
'Jasmine received a result after the suite finished:'
|
|
||||||
);
|
|
||||||
/* eslint-disable-next-line no-console */
|
|
||||||
expect(console.error).toHaveBeenCalledWith(
|
|
||||||
jasmine.objectContaining({
|
|
||||||
message: 'a very late error thrown',
|
|
||||||
globalErrorType: 'afterAll'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('routes all errors that occur during stack clearing somewhere', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn) {
|
|
||||||
clearTimeout(fn);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
|
|
||||||
const realClearStack = jasmineUnderTest.getClearStack(global);
|
|
||||||
let clearStackCallCount = 0;
|
|
||||||
let jasmineDone = false;
|
|
||||||
const expectedErrors = [];
|
|
||||||
const expectedErrorsAfterJasmineDone = [];
|
|
||||||
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
|
|
||||||
clearStackCallCount++;
|
|
||||||
const msg = `Error in clearStack #${clearStackCallCount}`;
|
|
||||||
|
|
||||||
if (jasmineDone) {
|
|
||||||
expectedErrorsAfterJasmineDone.push(`${msg} thrown`);
|
|
||||||
} else {
|
|
||||||
expectedErrors.push(`${msg} thrown`);
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchErrorEvent(global, { error: msg });
|
|
||||||
realClearStack(fn);
|
|
||||||
});
|
|
||||||
spyOn(console, 'error');
|
|
||||||
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
|
|
||||||
const receivedErrors = [];
|
|
||||||
function logErrors(event) {
|
|
||||||
for (const failure of event.failedExpectations) {
|
|
||||||
receivedErrors.push(failure.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env.addReporter({
|
|
||||||
specDone: logErrors,
|
|
||||||
suiteDone: logErrors,
|
|
||||||
jasmineDone: function(event) {
|
|
||||||
jasmineDone = true;
|
|
||||||
logErrors(event);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('A suite', function() {
|
|
||||||
env.it('is finishing when the failure occurs', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
expect(receivedErrors.length).toEqual(expectedErrors.length);
|
|
||||||
|
|
||||||
for (const e of expectedErrors) {
|
|
||||||
expect(receivedErrors).toContain(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const message of expectedErrorsAfterJasmineDone) {
|
|
||||||
/* eslint-disable-next-line no-console */
|
|
||||||
expect(console.error).toHaveBeenCalledWith(
|
|
||||||
jasmine.objectContaining({ message })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('reports multiple calls to done in the top suite as errors', async function() {
|
it('reports multiple calls to done in the top suite as errors', async function() {
|
||||||
const reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']);
|
const reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']);
|
||||||
const message =
|
const message =
|
||||||
@@ -2840,104 +2496,6 @@ describe('Env integration', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reports errors that occur during loading', async function() {
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn, delay) {
|
|
||||||
clearTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
},
|
|
||||||
onerror: function() {}
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env();
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', [
|
|
||||||
'jasmineDone',
|
|
||||||
'suiteDone',
|
|
||||||
'specDone'
|
|
||||||
]);
|
|
||||||
|
|
||||||
env.addReporter(reporter);
|
|
||||||
dispatchErrorEvent(global, {
|
|
||||||
message: 'Uncaught SyntaxError: Unexpected end of input',
|
|
||||||
error: undefined,
|
|
||||||
filename: 'borkenSpec.js',
|
|
||||||
lineno: 42
|
|
||||||
});
|
|
||||||
const error = new Error('ENOCHEESE');
|
|
||||||
dispatchErrorEvent(global, { error });
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
const e = reporter.jasmineDone.calls.argsFor(0)[0];
|
|
||||||
expect(e.failedExpectations).toEqual([
|
|
||||||
{
|
|
||||||
passed: false,
|
|
||||||
globalErrorType: 'load',
|
|
||||||
message: 'Uncaught SyntaxError: Unexpected end of input',
|
|
||||||
stack: undefined,
|
|
||||||
filename: 'borkenSpec.js',
|
|
||||||
lineno: 42
|
|
||||||
},
|
|
||||||
{
|
|
||||||
passed: false,
|
|
||||||
globalErrorType: 'load',
|
|
||||||
message: 'ENOCHEESE',
|
|
||||||
stack: error.stack,
|
|
||||||
filename: undefined,
|
|
||||||
lineno: undefined
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('If suppressLoadErrors: true was passed', function() {
|
|
||||||
it('does not install a global error handler during loading', async function() {
|
|
||||||
const originalOnerror = jasmine.createSpy('original onerror');
|
|
||||||
const global = {
|
|
||||||
...browserEventMethods(),
|
|
||||||
setTimeout: function(fn, delay) {
|
|
||||||
return setTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
clearTimeout: function(fn, delay) {
|
|
||||||
clearTimeout(fn, delay);
|
|
||||||
},
|
|
||||||
queueMicrotask: function(fn) {
|
|
||||||
queueMicrotask(fn);
|
|
||||||
},
|
|
||||||
onerror: originalOnerror
|
|
||||||
};
|
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
|
||||||
const globalErrors = new jasmineUnderTest.GlobalErrors(global);
|
|
||||||
const onerror = jasmine.createSpy('onerror');
|
|
||||||
globalErrors.pushListener(onerror);
|
|
||||||
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
|
|
||||||
|
|
||||||
env.cleanup_();
|
|
||||||
env = new jasmineUnderTest.Env({ suppressLoadErrors: true });
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', [
|
|
||||||
'jasmineDone',
|
|
||||||
'suiteDone',
|
|
||||||
'specDone'
|
|
||||||
]);
|
|
||||||
|
|
||||||
env.addReporter(reporter);
|
|
||||||
global.onerror('Uncaught Error: ENOCHEESE');
|
|
||||||
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
const e = reporter.jasmineDone.calls.argsFor(0)[0];
|
|
||||||
expect(e.failedExpectations).toEqual([]);
|
|
||||||
expect(originalOnerror).toHaveBeenCalledWith('Uncaught Error: ENOCHEESE');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overall status in the jasmineDone event', function() {
|
describe('Overall status in the jasmineDone event', function() {
|
||||||
describe('When everything passes', function() {
|
describe('When everything passes', function() {
|
||||||
it('is "passed"', async function() {
|
it('is "passed"', async function() {
|
||||||
@@ -3884,347 +3442,6 @@ describe('Env integration', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#spyOnGlobalErrorsAsync', function() {
|
|
||||||
const leftInstalledMessage =
|
|
||||||
'Global error spy was not uninstalled. ' +
|
|
||||||
'(Did you forget to await the return value of spyOnGlobalErrorsAsync?)';
|
|
||||||
|
|
||||||
function resultForRunable(reporterSpy, fullName) {
|
|
||||||
const match = reporterSpy.calls.all().find(function(call) {
|
|
||||||
return call.args[0].fullName === fullName;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!match) {
|
|
||||||
throw new Error(`No result for runable "${fullName}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return match.args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
it('allows global errors to be suppressed and spied on', async function() {
|
|
||||||
env.it('a passing spec', async function() {
|
|
||||||
await env.spyOnGlobalErrorsAsync(async spy => {
|
|
||||||
setTimeout(() => {
|
|
||||||
throw new Error('nope');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
env.expect(spy).toHaveBeenCalledWith(new Error('nope'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('a failing spec', async function() {
|
|
||||||
await env.spyOnGlobalErrorsAsync(async spy => {
|
|
||||||
setTimeout(() => {
|
|
||||||
throw new Error('yep');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
env.expect(spy).toHaveBeenCalledWith(new Error('nope'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
|
||||||
env.addReporter(reporter);
|
|
||||||
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
// Verify that there were no unexpected errors
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledTimes(2);
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(new Error('nope'));
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(new Error('yep'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const passingResult = resultForRunable(
|
|
||||||
reporter.specDone,
|
|
||||||
'a passing spec'
|
|
||||||
);
|
|
||||||
expect(passingResult.status).toEqual('passed');
|
|
||||||
expect(passingResult.failedExpectations).toEqual([]);
|
|
||||||
|
|
||||||
const failingResult = resultForRunable(
|
|
||||||
reporter.specDone,
|
|
||||||
'a failing spec'
|
|
||||||
);
|
|
||||||
expect(failingResult.status).toEqual('failed');
|
|
||||||
expect(failingResult.failedExpectations[0].message).toMatch(
|
|
||||||
/Expected \$\[0] = Error: yep to equal Error: nope\./
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cleans up if the global error spy is left installed in a beforeAll', async function() {
|
|
||||||
env.configure({ random: false });
|
|
||||||
|
|
||||||
env.describe('Suite 1', function() {
|
|
||||||
env.beforeAll(async function() {
|
|
||||||
env.spyOnGlobalErrorsAsync(function() {
|
|
||||||
// Never resolves
|
|
||||||
return new Promise(() => {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('a spec', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('Suite 2', function() {
|
|
||||||
env.it('a spec', async function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
throw new Error('should fail the spec');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', [
|
|
||||||
'specDone',
|
|
||||||
'suiteDone'
|
|
||||||
]);
|
|
||||||
env.addReporter(reporter);
|
|
||||||
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
// Verify that there were no unexpected errors
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(
|
|
||||||
new Error('should fail the spec')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const suiteResult = resultForRunable(reporter.suiteDone, 'Suite 1');
|
|
||||||
expect(suiteResult.status).toEqual('failed');
|
|
||||||
expect(suiteResult.failedExpectations.length).toEqual(1);
|
|
||||||
expect(suiteResult.failedExpectations[0].message).toEqual(
|
|
||||||
leftInstalledMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
const specResult = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
|
||||||
expect(specResult.status).toEqual('failed');
|
|
||||||
expect(specResult.failedExpectations.length).toEqual(1);
|
|
||||||
expect(specResult.failedExpectations[0].message).toMatch(
|
|
||||||
/Error: should fail the spec/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cleans up if the global error spy is left installed in an afterAll', async function() {
|
|
||||||
env.configure({ random: false });
|
|
||||||
|
|
||||||
env.describe('Suite 1', function() {
|
|
||||||
env.afterAll(async function() {
|
|
||||||
env.spyOnGlobalErrorsAsync(function() {
|
|
||||||
// Never resolves
|
|
||||||
return new Promise(() => {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('a spec', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('Suite 2', function() {
|
|
||||||
env.it('a spec', async function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
throw new Error('should fail the spec');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', [
|
|
||||||
'specDone',
|
|
||||||
'suiteDone'
|
|
||||||
]);
|
|
||||||
env.addReporter(reporter);
|
|
||||||
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
// Verify that there were no unexpected errors
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(
|
|
||||||
new Error('should fail the spec')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable(
|
|
||||||
'Suite 1',
|
|
||||||
[leftInstalledMessage]
|
|
||||||
);
|
|
||||||
|
|
||||||
const suiteResult = resultForRunable(reporter.suiteDone, 'Suite 1');
|
|
||||||
expect(suiteResult.status).toEqual('failed');
|
|
||||||
expect(suiteResult.failedExpectations.length).toEqual(1);
|
|
||||||
expect(suiteResult.failedExpectations[0].message).toEqual(
|
|
||||||
leftInstalledMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
const specResult = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
|
||||||
expect(specResult.status).toEqual('failed');
|
|
||||||
expect(specResult.failedExpectations.length).toEqual(1);
|
|
||||||
expect(specResult.failedExpectations[0].message).toMatch(
|
|
||||||
/Error: should fail the spec/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cleans up if the global error spy is left installed in a beforeEach', async function() {
|
|
||||||
env.configure({ random: false });
|
|
||||||
|
|
||||||
env.describe('Suite 1', function() {
|
|
||||||
env.beforeEach(async function() {
|
|
||||||
env.spyOnGlobalErrorsAsync(function() {
|
|
||||||
// Never resolves
|
|
||||||
return new Promise(() => {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('a spec', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('Suite 2', function() {
|
|
||||||
env.it('a spec', async function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
throw new Error('should fail the spec');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', [
|
|
||||||
'specDone',
|
|
||||||
'suiteDone'
|
|
||||||
]);
|
|
||||||
env.addReporter(reporter);
|
|
||||||
|
|
||||||
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
// Verify that there were no unexpected errors
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(
|
|
||||||
new Error('should fail the spec')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const spec1Result = resultForRunable(reporter.specDone, 'Suite 1 a spec');
|
|
||||||
expect(spec1Result.status).toEqual('failed');
|
|
||||||
expect(spec1Result.failedExpectations.length).toEqual(1);
|
|
||||||
expect(spec1Result.failedExpectations[0].message).toEqual(
|
|
||||||
leftInstalledMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
const spec2Result = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
|
||||||
expect(spec2Result.status).toEqual('failed');
|
|
||||||
expect(spec2Result.failedExpectations.length).toEqual(1);
|
|
||||||
expect(spec2Result.failedExpectations[0].message).toMatch(
|
|
||||||
/Error: should fail the spec/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cleans up if the global error spy is left installed in an it', async function() {
|
|
||||||
env.configure({ random: false });
|
|
||||||
|
|
||||||
env.it('spec 1', async function() {
|
|
||||||
env.spyOnGlobalErrorsAsync(function() {
|
|
||||||
// Never resolves
|
|
||||||
return new Promise(() => {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('spec 2', async function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
throw new Error('should fail the spec');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
|
||||||
env.addReporter(reporter);
|
|
||||||
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
// Verify that there were no unexpected errors
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(
|
|
||||||
new Error('should fail the spec')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const spec1Result = resultForRunable(reporter.specDone, 'spec 1');
|
|
||||||
expect(spec1Result.status).toEqual('failed');
|
|
||||||
expect(spec1Result.failedExpectations.length).toEqual(1);
|
|
||||||
expect(spec1Result.failedExpectations[0].message).toEqual(
|
|
||||||
leftInstalledMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
const spec2Result = resultForRunable(reporter.specDone, 'spec 2');
|
|
||||||
expect(spec2Result.status).toEqual('failed');
|
|
||||||
expect(spec2Result.failedExpectations.length).toEqual(1);
|
|
||||||
expect(spec2Result.failedExpectations[0].message).toMatch(
|
|
||||||
/Error: should fail the spec/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cleans up if the global error spy is left installed in an afterEach', async function() {
|
|
||||||
env.configure({ random: false });
|
|
||||||
|
|
||||||
env.describe('Suite 1', function() {
|
|
||||||
env.afterEach(async function() {
|
|
||||||
env.spyOnGlobalErrorsAsync(function() {
|
|
||||||
// Never resolves
|
|
||||||
return new Promise(() => {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('a spec', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('Suite 2', function() {
|
|
||||||
env.it('a spec', async function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
throw new Error('should fail the spec');
|
|
||||||
});
|
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const reporter = jasmine.createSpyObj('reporter', [
|
|
||||||
'specDone',
|
|
||||||
'suiteDone'
|
|
||||||
]);
|
|
||||||
env.addReporter(reporter);
|
|
||||||
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
|
||||||
await env.execute();
|
|
||||||
|
|
||||||
if (isBrowser) {
|
|
||||||
// Verify that there were no unexpected errors
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
|
||||||
expect(globalErrorSpy).toHaveBeenCalledWith(
|
|
||||||
new Error('should fail the spec')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const spec1Result = resultForRunable(reporter.specDone, 'Suite 1 a spec');
|
|
||||||
expect(spec1Result.status).toEqual('failed');
|
|
||||||
expect(spec1Result.failedExpectations.length).toEqual(1);
|
|
||||||
expect(spec1Result.failedExpectations[0].message).toEqual(
|
|
||||||
leftInstalledMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
const spec2Result = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
|
||||||
expect(spec2Result.status).toEqual('failed');
|
|
||||||
expect(spec2Result.failedExpectations.length).toEqual(1);
|
|
||||||
expect(spec2Result.failedExpectations[0].message).toMatch(
|
|
||||||
/Error: should fail the spec/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('reports a suite level error when a describe fn throws', async function() {
|
it('reports a suite level error when a describe fn throws', async function() {
|
||||||
const reporter = jasmine.createSpyObj('reporter', ['suiteDone']);
|
const reporter = jasmine.createSpyObj('reporter', ['suiteDone']);
|
||||||
env.addReporter(reporter);
|
env.addReporter(reporter);
|
||||||
|
|||||||
820
spec/core/integration/GlobalErrorHandlingSpec.js
Normal file
820
spec/core/integration/GlobalErrorHandlingSpec.js
Normal file
@@ -0,0 +1,820 @@
|
|||||||
|
describe('Global error handling (integration)', function() {
|
||||||
|
const isBrowser = typeof window !== 'undefined';
|
||||||
|
let env;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
specHelpers.registerIntegrationMatchers();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
env.cleanup_();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reports errors that occur during loading', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn, delay) {
|
||||||
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
},
|
||||||
|
onerror: function() {}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'jasmineDone',
|
||||||
|
'suiteDone',
|
||||||
|
'specDone'
|
||||||
|
]);
|
||||||
|
|
||||||
|
env.addReporter(reporter);
|
||||||
|
dispatchErrorEvent(global, {
|
||||||
|
message: 'Uncaught SyntaxError: Unexpected end of input',
|
||||||
|
error: undefined,
|
||||||
|
filename: 'borkenSpec.js',
|
||||||
|
lineno: 42
|
||||||
|
});
|
||||||
|
const error = new Error('ENOCHEESE');
|
||||||
|
dispatchErrorEvent(global, { error });
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
const e = reporter.jasmineDone.calls.argsFor(0)[0];
|
||||||
|
expect(e.failedExpectations).toEqual([
|
||||||
|
{
|
||||||
|
passed: false,
|
||||||
|
globalErrorType: 'load',
|
||||||
|
message: 'Uncaught SyntaxError: Unexpected end of input',
|
||||||
|
stack: undefined,
|
||||||
|
filename: 'borkenSpec.js',
|
||||||
|
lineno: 42
|
||||||
|
},
|
||||||
|
{
|
||||||
|
passed: false,
|
||||||
|
globalErrorType: 'load',
|
||||||
|
message: 'ENOCHEESE',
|
||||||
|
stack: error.stack,
|
||||||
|
filename: undefined,
|
||||||
|
lineno: undefined
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('If suppressLoadErrors: true was passed', function() {
|
||||||
|
it('does not install a global error handler during loading', async function() {
|
||||||
|
const originalOnerror = jasmine.createSpy('original onerror');
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn, delay) {
|
||||||
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
},
|
||||||
|
onerror: originalOnerror
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
const globalErrors = new jasmineUnderTest.GlobalErrors(global);
|
||||||
|
const onerror = jasmine.createSpy('onerror');
|
||||||
|
globalErrors.pushListener(onerror);
|
||||||
|
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
|
||||||
|
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env({ suppressLoadErrors: true });
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'jasmineDone',
|
||||||
|
'suiteDone',
|
||||||
|
'specDone'
|
||||||
|
]);
|
||||||
|
|
||||||
|
env.addReporter(reporter);
|
||||||
|
global.onerror('Uncaught Error: ENOCHEESE');
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
const e = reporter.jasmineDone.calls.argsFor(0)[0];
|
||||||
|
expect(e.failedExpectations).toEqual([]);
|
||||||
|
expect(originalOnerror).toHaveBeenCalledWith('Uncaught Error: ENOCHEESE');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Handling unhandled exceptions', function() {
|
||||||
|
it('routes unhandled exceptions to the running spec', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn, delay) {
|
||||||
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
const reporter = jasmine.createSpyObj('fakeReporter', [
|
||||||
|
'specDone',
|
||||||
|
'suiteDone'
|
||||||
|
]);
|
||||||
|
|
||||||
|
env.addReporter(reporter);
|
||||||
|
|
||||||
|
env.describe('A suite', function() {
|
||||||
|
env.it('fails', function(specDone) {
|
||||||
|
setTimeout(function() {
|
||||||
|
dispatchErrorEvent(global, { error: 'fail' });
|
||||||
|
specDone();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
expect(reporter.specDone).toHaveFailedExpectationsForRunnable(
|
||||||
|
'A suite fails',
|
||||||
|
['fail thrown']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When the most recently running spec has reported specDone', function() {
|
||||||
|
it('routes unhandled exceptions to an ancestor suite', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn) {
|
||||||
|
clearTimeout(fn);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
|
||||||
|
const realClearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
const clearStackCallbacks = {};
|
||||||
|
let clearStackCallCount = 0;
|
||||||
|
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
|
||||||
|
clearStackCallCount++;
|
||||||
|
|
||||||
|
if (clearStackCallbacks[clearStackCallCount]) {
|
||||||
|
clearStackCallbacks[clearStackCallCount]();
|
||||||
|
}
|
||||||
|
|
||||||
|
realClearStack(fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
|
||||||
|
let suiteErrors = [];
|
||||||
|
env.addReporter({
|
||||||
|
suiteDone: function(result) {
|
||||||
|
const messages = result.failedExpectations.map(e => e.message);
|
||||||
|
suiteErrors = suiteErrors.concat(messages);
|
||||||
|
},
|
||||||
|
specDone: function() {
|
||||||
|
clearStackCallbacks[clearStackCallCount + 1] = function() {
|
||||||
|
dispatchErrorEvent(global, {
|
||||||
|
error: 'fail at the end of the reporter queue'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
clearStackCallbacks[clearStackCallCount + 2] = function() {
|
||||||
|
dispatchErrorEvent(global, {
|
||||||
|
error: 'fail at the end of the spec queue'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('A suite', function() {
|
||||||
|
env.it('is finishing when the failure occurs', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
expect(suiteErrors).toEqual([
|
||||||
|
'fail at the end of the reporter queue thrown',
|
||||||
|
'fail at the end of the spec queue thrown'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('routes unhandled exceptions to the running suite', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn, delay) {
|
||||||
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
const reporter = jasmine.createSpyObj('fakeReporter', [
|
||||||
|
'specDone',
|
||||||
|
'suiteDone'
|
||||||
|
]);
|
||||||
|
|
||||||
|
env.addReporter(reporter);
|
||||||
|
|
||||||
|
env.fdescribe('A suite', function() {
|
||||||
|
env.it('fails', function(specDone) {
|
||||||
|
setTimeout(function() {
|
||||||
|
specDone();
|
||||||
|
queueMicrotask(function() {
|
||||||
|
queueMicrotask(function() {
|
||||||
|
dispatchErrorEvent(global, { error: 'fail' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('Ignored', function() {
|
||||||
|
env.it('is not run', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
expect(reporter.specDone).not.toHaveFailedExpectationsForRunnable(
|
||||||
|
'A suite fails',
|
||||||
|
['fail thrown']
|
||||||
|
);
|
||||||
|
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable(
|
||||||
|
'A suite',
|
||||||
|
['fail thrown']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When the most recently suite has reported suiteDone', function() {
|
||||||
|
it('routes unhandled exceptions errors to an ancestor suite', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn, delay) {
|
||||||
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
|
||||||
|
const realClearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
const clearStackCallbacks = {};
|
||||||
|
let clearStackCallCount = 0;
|
||||||
|
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
|
||||||
|
clearStackCallCount++;
|
||||||
|
|
||||||
|
if (clearStackCallbacks[clearStackCallCount]) {
|
||||||
|
clearStackCallbacks[clearStackCallCount]();
|
||||||
|
}
|
||||||
|
|
||||||
|
realClearStack(fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
|
||||||
|
let suiteErrors = [];
|
||||||
|
env.addReporter({
|
||||||
|
suiteDone: function(result) {
|
||||||
|
const messages = result.failedExpectations.map(e => e.message);
|
||||||
|
suiteErrors = suiteErrors.concat(messages);
|
||||||
|
|
||||||
|
if (result.description === 'A nested suite') {
|
||||||
|
clearStackCallbacks[clearStackCallCount + 1] = function() {
|
||||||
|
dispatchErrorEvent(global, {
|
||||||
|
error: 'fail at the end of the reporter queue'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
clearStackCallbacks[clearStackCallCount + 2] = function() {
|
||||||
|
dispatchErrorEvent(global, {
|
||||||
|
error: 'fail at the end of the suite queue'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('A suite', function() {
|
||||||
|
env.describe('A nested suite', function() {
|
||||||
|
env.it('a spec', function() {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
expect(suiteErrors).toEqual([
|
||||||
|
'fail at the end of the reporter queue thrown',
|
||||||
|
'fail at the end of the suite queue thrown'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When the env has started reporting jasmineDone', function() {
|
||||||
|
it('logs the error to the console', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn, delay) {
|
||||||
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
|
||||||
|
spyOn(console, 'error');
|
||||||
|
|
||||||
|
env.addReporter({
|
||||||
|
jasmineDone: function() {
|
||||||
|
dispatchErrorEvent(global, { error: 'a very late error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('a spec', function() {});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
/* eslint-disable-next-line no-console */
|
||||||
|
expect(console.error).toHaveBeenCalledWith(
|
||||||
|
'Jasmine received a result after the suite finished:'
|
||||||
|
);
|
||||||
|
/* eslint-disable-next-line no-console */
|
||||||
|
expect(console.error).toHaveBeenCalledWith(
|
||||||
|
jasmine.objectContaining({
|
||||||
|
message: 'a very late error thrown',
|
||||||
|
globalErrorType: 'afterAll'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('routes all errors that occur during stack clearing somewhere', async function() {
|
||||||
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
|
setTimeout: function(fn, delay) {
|
||||||
|
return setTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
clearTimeout: function(fn) {
|
||||||
|
clearTimeout(fn);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
|
|
||||||
|
const realClearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
let clearStackCallCount = 0;
|
||||||
|
let jasmineDone = false;
|
||||||
|
const expectedErrors = [];
|
||||||
|
const expectedErrorsAfterJasmineDone = [];
|
||||||
|
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
|
||||||
|
clearStackCallCount++;
|
||||||
|
const msg = `Error in clearStack #${clearStackCallCount}`;
|
||||||
|
|
||||||
|
if (jasmineDone) {
|
||||||
|
expectedErrorsAfterJasmineDone.push(`${msg} thrown`);
|
||||||
|
} else {
|
||||||
|
expectedErrors.push(`${msg} thrown`);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchErrorEvent(global, { error: msg });
|
||||||
|
realClearStack(fn);
|
||||||
|
});
|
||||||
|
spyOn(console, 'error');
|
||||||
|
|
||||||
|
env.cleanup_();
|
||||||
|
env = new jasmineUnderTest.Env();
|
||||||
|
|
||||||
|
const receivedErrors = [];
|
||||||
|
function logErrors(event) {
|
||||||
|
for (const failure of event.failedExpectations) {
|
||||||
|
receivedErrors.push(failure.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env.addReporter({
|
||||||
|
specDone: logErrors,
|
||||||
|
suiteDone: logErrors,
|
||||||
|
jasmineDone: function(event) {
|
||||||
|
jasmineDone = true;
|
||||||
|
logErrors(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('A suite', function() {
|
||||||
|
env.it('is finishing when the failure occurs', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
expect(receivedErrors.length).toEqual(expectedErrors.length);
|
||||||
|
|
||||||
|
for (const e of expectedErrors) {
|
||||||
|
expect(receivedErrors).toContain(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const message of expectedErrorsAfterJasmineDone) {
|
||||||
|
/* eslint-disable-next-line no-console */
|
||||||
|
expect(console.error).toHaveBeenCalledWith(
|
||||||
|
jasmine.objectContaining({ message })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#spyOnGlobalErrorsAsync', function() {
|
||||||
|
const leftInstalledMessage =
|
||||||
|
'Global error spy was not uninstalled. ' +
|
||||||
|
'(Did you forget to await the return value of spyOnGlobalErrorsAsync?)';
|
||||||
|
|
||||||
|
function resultForRunable(reporterSpy, fullName) {
|
||||||
|
const match = reporterSpy.calls.all().find(function(call) {
|
||||||
|
return call.args[0].fullName === fullName;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(`No result for runable "${fullName}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return match.args[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
it('allows global errors to be suppressed and spied on', async function() {
|
||||||
|
env.it('a passing spec', async function() {
|
||||||
|
await env.spyOnGlobalErrorsAsync(async spy => {
|
||||||
|
setTimeout(() => {
|
||||||
|
throw new Error('nope');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
env.expect(spy).toHaveBeenCalledWith(new Error('nope'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('a failing spec', async function() {
|
||||||
|
await env.spyOnGlobalErrorsAsync(async spy => {
|
||||||
|
setTimeout(() => {
|
||||||
|
throw new Error('yep');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
env.expect(spy).toHaveBeenCalledWith(new Error('nope'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
||||||
|
env.addReporter(reporter);
|
||||||
|
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
// Verify that there were no unexpected errors
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledTimes(2);
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(new Error('nope'));
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(new Error('yep'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const passingResult = resultForRunable(
|
||||||
|
reporter.specDone,
|
||||||
|
'a passing spec'
|
||||||
|
);
|
||||||
|
expect(passingResult.status).toEqual('passed');
|
||||||
|
expect(passingResult.failedExpectations).toEqual([]);
|
||||||
|
|
||||||
|
const failingResult = resultForRunable(
|
||||||
|
reporter.specDone,
|
||||||
|
'a failing spec'
|
||||||
|
);
|
||||||
|
expect(failingResult.status).toEqual('failed');
|
||||||
|
expect(failingResult.failedExpectations[0].message).toMatch(
|
||||||
|
/Expected \$\[0] = Error: yep to equal Error: nope\./
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cleans up if the global error spy is left installed in a beforeAll', async function() {
|
||||||
|
env.configure({ random: false });
|
||||||
|
|
||||||
|
env.describe('Suite 1', function() {
|
||||||
|
env.beforeAll(async function() {
|
||||||
|
env.spyOnGlobalErrorsAsync(function() {
|
||||||
|
// Never resolves
|
||||||
|
return new Promise(() => {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('a spec', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('Suite 2', function() {
|
||||||
|
env.it('a spec', async function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
throw new Error('should fail the spec');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'specDone',
|
||||||
|
'suiteDone'
|
||||||
|
]);
|
||||||
|
env.addReporter(reporter);
|
||||||
|
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
// Verify that there were no unexpected errors
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(
|
||||||
|
new Error('should fail the spec')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const suiteResult = resultForRunable(reporter.suiteDone, 'Suite 1');
|
||||||
|
expect(suiteResult.status).toEqual('failed');
|
||||||
|
expect(suiteResult.failedExpectations.length).toEqual(1);
|
||||||
|
expect(suiteResult.failedExpectations[0].message).toEqual(
|
||||||
|
leftInstalledMessage
|
||||||
|
);
|
||||||
|
|
||||||
|
const specResult = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
||||||
|
expect(specResult.status).toEqual('failed');
|
||||||
|
expect(specResult.failedExpectations.length).toEqual(1);
|
||||||
|
expect(specResult.failedExpectations[0].message).toMatch(
|
||||||
|
/Error: should fail the spec/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cleans up if the global error spy is left installed in an afterAll', async function() {
|
||||||
|
env.configure({ random: false });
|
||||||
|
|
||||||
|
env.describe('Suite 1', function() {
|
||||||
|
env.afterAll(async function() {
|
||||||
|
env.spyOnGlobalErrorsAsync(function() {
|
||||||
|
// Never resolves
|
||||||
|
return new Promise(() => {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('a spec', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('Suite 2', function() {
|
||||||
|
env.it('a spec', async function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
throw new Error('should fail the spec');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'specDone',
|
||||||
|
'suiteDone'
|
||||||
|
]);
|
||||||
|
env.addReporter(reporter);
|
||||||
|
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
// Verify that there were no unexpected errors
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(
|
||||||
|
new Error('should fail the spec')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable(
|
||||||
|
'Suite 1',
|
||||||
|
[leftInstalledMessage]
|
||||||
|
);
|
||||||
|
|
||||||
|
const suiteResult = resultForRunable(reporter.suiteDone, 'Suite 1');
|
||||||
|
expect(suiteResult.status).toEqual('failed');
|
||||||
|
expect(suiteResult.failedExpectations.length).toEqual(1);
|
||||||
|
expect(suiteResult.failedExpectations[0].message).toEqual(
|
||||||
|
leftInstalledMessage
|
||||||
|
);
|
||||||
|
|
||||||
|
const specResult = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
||||||
|
expect(specResult.status).toEqual('failed');
|
||||||
|
expect(specResult.failedExpectations.length).toEqual(1);
|
||||||
|
expect(specResult.failedExpectations[0].message).toMatch(
|
||||||
|
/Error: should fail the spec/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cleans up if the global error spy is left installed in a beforeEach', async function() {
|
||||||
|
env.configure({ random: false });
|
||||||
|
|
||||||
|
env.describe('Suite 1', function() {
|
||||||
|
env.beforeEach(async function() {
|
||||||
|
env.spyOnGlobalErrorsAsync(function() {
|
||||||
|
// Never resolves
|
||||||
|
return new Promise(() => {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('a spec', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('Suite 2', function() {
|
||||||
|
env.it('a spec', async function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
throw new Error('should fail the spec');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'specDone',
|
||||||
|
'suiteDone'
|
||||||
|
]);
|
||||||
|
env.addReporter(reporter);
|
||||||
|
|
||||||
|
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
// Verify that there were no unexpected errors
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(
|
||||||
|
new Error('should fail the spec')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const spec1Result = resultForRunable(reporter.specDone, 'Suite 1 a spec');
|
||||||
|
expect(spec1Result.status).toEqual('failed');
|
||||||
|
expect(spec1Result.failedExpectations.length).toEqual(1);
|
||||||
|
expect(spec1Result.failedExpectations[0].message).toEqual(
|
||||||
|
leftInstalledMessage
|
||||||
|
);
|
||||||
|
|
||||||
|
const spec2Result = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
||||||
|
expect(spec2Result.status).toEqual('failed');
|
||||||
|
expect(spec2Result.failedExpectations.length).toEqual(1);
|
||||||
|
expect(spec2Result.failedExpectations[0].message).toMatch(
|
||||||
|
/Error: should fail the spec/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cleans up if the global error spy is left installed in an it', async function() {
|
||||||
|
env.configure({ random: false });
|
||||||
|
|
||||||
|
env.it('spec 1', async function() {
|
||||||
|
env.spyOnGlobalErrorsAsync(function() {
|
||||||
|
// Never resolves
|
||||||
|
return new Promise(() => {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('spec 2', async function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
throw new Error('should fail the spec');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
});
|
||||||
|
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
||||||
|
env.addReporter(reporter);
|
||||||
|
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
// Verify that there were no unexpected errors
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(
|
||||||
|
new Error('should fail the spec')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const spec1Result = resultForRunable(reporter.specDone, 'spec 1');
|
||||||
|
expect(spec1Result.status).toEqual('failed');
|
||||||
|
expect(spec1Result.failedExpectations.length).toEqual(1);
|
||||||
|
expect(spec1Result.failedExpectations[0].message).toEqual(
|
||||||
|
leftInstalledMessage
|
||||||
|
);
|
||||||
|
|
||||||
|
const spec2Result = resultForRunable(reporter.specDone, 'spec 2');
|
||||||
|
expect(spec2Result.status).toEqual('failed');
|
||||||
|
expect(spec2Result.failedExpectations.length).toEqual(1);
|
||||||
|
expect(spec2Result.failedExpectations[0].message).toMatch(
|
||||||
|
/Error: should fail the spec/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cleans up if the global error spy is left installed in an afterEach', async function() {
|
||||||
|
env.configure({ random: false });
|
||||||
|
|
||||||
|
env.describe('Suite 1', function() {
|
||||||
|
env.afterEach(async function() {
|
||||||
|
env.spyOnGlobalErrorsAsync(function() {
|
||||||
|
// Never resolves
|
||||||
|
return new Promise(() => {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it('a spec', function() {});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.describe('Suite 2', function() {
|
||||||
|
env.it('a spec', async function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
throw new Error('should fail the spec');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const reporter = jasmine.createSpyObj('reporter', [
|
||||||
|
'specDone',
|
||||||
|
'suiteDone'
|
||||||
|
]);
|
||||||
|
env.addReporter(reporter);
|
||||||
|
await jasmine.spyOnGlobalErrorsAsync(async function(globalErrorSpy) {
|
||||||
|
await env.execute();
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
// Verify that there were no unexpected errors
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(globalErrorSpy).toHaveBeenCalledWith(
|
||||||
|
new Error('should fail the spec')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const spec1Result = resultForRunable(reporter.specDone, 'Suite 1 a spec');
|
||||||
|
expect(spec1Result.status).toEqual('failed');
|
||||||
|
expect(spec1Result.failedExpectations.length).toEqual(1);
|
||||||
|
expect(spec1Result.failedExpectations[0].message).toEqual(
|
||||||
|
leftInstalledMessage
|
||||||
|
);
|
||||||
|
|
||||||
|
const spec2Result = resultForRunable(reporter.specDone, 'Suite 2 a spec');
|
||||||
|
expect(spec2Result.status).toEqual('failed');
|
||||||
|
expect(spec2Result.failedExpectations.length).toEqual(1);
|
||||||
|
expect(spec2Result.failedExpectations[0].message).toMatch(
|
||||||
|
/Error: should fail the spec/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function browserEventMethods() {
|
||||||
|
return {
|
||||||
|
listeners_: { error: [], unhandledrejection: [] },
|
||||||
|
addEventListener(eventName, listener) {
|
||||||
|
this.listeners_[eventName].push(listener);
|
||||||
|
},
|
||||||
|
removeEventListener(eventName, listener) {
|
||||||
|
this.listeners_[eventName] = this.listeners_[eventName].filter(
|
||||||
|
l => l !== listener
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispatchErrorEvent(global, event) {
|
||||||
|
expect(global.listeners_.error.length)
|
||||||
|
.withContext('number of error listeners')
|
||||||
|
.toBeGreaterThan(0);
|
||||||
|
|
||||||
|
for (const l of global.listeners_.error) {
|
||||||
|
l(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user