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() {
|
||||
const reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']);
|
||||
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('When everything passes', 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() {
|
||||
const reporter = jasmine.createSpyObj('reporter', ['suiteDone']);
|
||||
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