The old style of merging all of a function's variable declarations into a single statement made some sense back in the days of var, but there's no reason to keep doing it now that we use const and let.
469 lines
14 KiB
JavaScript
469 lines
14 KiB
JavaScript
describe('Suite', function() {
|
|
let env;
|
|
|
|
beforeEach(function() {
|
|
env = new privateUnderTest.Env();
|
|
});
|
|
|
|
afterEach(function() {
|
|
env.cleanup_();
|
|
});
|
|
|
|
it('keeps its id', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
id: 456,
|
|
description: 'I am a suite'
|
|
});
|
|
|
|
expect(suite.id).toEqual(456);
|
|
});
|
|
|
|
it('returns blank full name for top level suite', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a suite'
|
|
});
|
|
|
|
expect(suite.getFullName()).toEqual('');
|
|
});
|
|
|
|
it('returns its full name when it has parent suites', function() {
|
|
const parentSuite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a parent suite',
|
|
parentSuite: jasmine.createSpy('pretend top level suite')
|
|
});
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a suite',
|
|
parentSuite: parentSuite
|
|
});
|
|
|
|
expect(suite.getFullName()).toEqual('I am a parent suite I am a suite');
|
|
});
|
|
|
|
it('adds beforeEach functions in order of needed execution', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a suite'
|
|
});
|
|
const outerBefore = { fn: 'outerBeforeEach' };
|
|
const innerBefore = { fn: 'insideBeforeEach' };
|
|
|
|
suite.beforeEach(outerBefore);
|
|
suite.beforeEach(innerBefore);
|
|
|
|
expect(suite.beforeFns).toEqual([
|
|
{ fn: innerBefore.fn, suite },
|
|
{ fn: outerBefore.fn, suite }
|
|
]);
|
|
});
|
|
|
|
it('adds beforeAll functions in order of needed execution', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a suite'
|
|
});
|
|
const outerBefore = { fn: 'outerBeforeAll' };
|
|
const innerBefore = { fn: 'insideBeforeAll' };
|
|
|
|
suite.beforeAll(outerBefore);
|
|
suite.beforeAll(innerBefore);
|
|
|
|
expect(suite.beforeAllFns).toEqual([
|
|
{ fn: outerBefore.fn, type: 'beforeAll', suite: jasmine.is(suite) },
|
|
{ fn: innerBefore.fn, type: 'beforeAll', suite: jasmine.is(suite) }
|
|
]);
|
|
});
|
|
|
|
it('adds afterEach functions in order of needed execution', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a suite'
|
|
});
|
|
const outerAfter = { fn: 'outerAfterEach' };
|
|
const innerAfter = { fn: 'insideAfterEach' };
|
|
|
|
suite.afterEach(outerAfter);
|
|
suite.afterEach(innerAfter);
|
|
|
|
expect(suite.afterFns).toEqual([
|
|
{ fn: innerAfter.fn, suite, type: 'afterEach' },
|
|
{ fn: outerAfter.fn, suite, type: 'afterEach' }
|
|
]);
|
|
});
|
|
|
|
it('adds afterAll functions in order of needed execution', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
description: 'I am a suite'
|
|
});
|
|
const outerAfter = { fn: 'outerAfterAll' };
|
|
const innerAfter = { fn: 'insideAfterAl' };
|
|
|
|
suite.afterAll(outerAfter);
|
|
suite.afterAll(innerAfter);
|
|
|
|
expect(suite.afterAllFns).toEqual([
|
|
{ fn: innerAfter.fn, type: 'afterAll' },
|
|
{ fn: outerAfter.fn, type: 'afterAll' }
|
|
]);
|
|
});
|
|
|
|
it('has a status of failed if any expectations have failed', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
|
|
suite.addExpectationResult(false, {});
|
|
expect(suite.doneEvent().status).toBe('failed');
|
|
});
|
|
|
|
it('retrieves a result with updated status', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
|
|
expect(suite.doneEvent().status).toBe('passed');
|
|
});
|
|
|
|
it('retrieves a result with pending status', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
suite.pend();
|
|
|
|
expect(suite.doneEvent().status).toBe('pending');
|
|
});
|
|
|
|
it('throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
throwOnExpectationFailure: true
|
|
});
|
|
|
|
expect(function() {
|
|
suite.addExpectationResult(false, { message: 'failed' });
|
|
}).toThrowError(jasmineUnderTest.private.errors.ExpectationFailed);
|
|
|
|
expect(suite.doneEvent().status).toBe('failed');
|
|
expect(suite.doneEvent().failedExpectations).toEqual([
|
|
jasmine.objectContaining({ message: 'failed' })
|
|
]);
|
|
});
|
|
|
|
it('does not add an additional failure when an expectation fails', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
|
|
suite.handleException(
|
|
new jasmineUnderTest.private.errors.ExpectationFailed()
|
|
);
|
|
|
|
expect(suite.doneEvent().failedExpectations).toEqual([]);
|
|
});
|
|
|
|
it('forwards late expectation failures to onLateError', function() {
|
|
const onLateError = jasmine.createSpy('onLateError');
|
|
const suite = new privateUnderTest.Suite({ onLateError });
|
|
const data = {
|
|
matcherName: '',
|
|
passed: false,
|
|
expected: '',
|
|
actual: '',
|
|
error: new Error('nope')
|
|
};
|
|
|
|
suite.reportedDone = true;
|
|
suite.addExpectationResult(false, data, true);
|
|
|
|
expect(onLateError).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({
|
|
message: jasmine.stringMatching(/^Error: nope/)
|
|
})
|
|
);
|
|
expect(suite.doneEvent().failedExpectations).toEqual([]);
|
|
});
|
|
|
|
it('does not forward non-late expectation failures to onLateError', function() {
|
|
const onLateError = jasmine.createSpy('onLateError');
|
|
const suite = new privateUnderTest.Suite({
|
|
onLateError
|
|
});
|
|
const data = {
|
|
matcherName: '',
|
|
passed: false,
|
|
expected: '',
|
|
actual: '',
|
|
error: new Error('nope')
|
|
};
|
|
|
|
suite.addExpectationResult(false, data, true);
|
|
|
|
expect(onLateError).not.toHaveBeenCalled();
|
|
expect(suite.doneEvent().failedExpectations.length).toEqual(1);
|
|
});
|
|
|
|
it('forwards late handleException calls to onLateError', function() {
|
|
const onLateError = jasmine.createSpy('onLateError');
|
|
const suite = new privateUnderTest.Suite({
|
|
onLateError
|
|
});
|
|
const error = new Error('oops');
|
|
|
|
suite.reportedDone = true;
|
|
suite.handleException(error);
|
|
|
|
expect(onLateError).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({
|
|
message: jasmine.stringMatching(/^Error: oops/)
|
|
})
|
|
);
|
|
expect(suite.doneEvent().failedExpectations).toEqual([]);
|
|
});
|
|
|
|
it('does not forward non-late handleException calls to onLateError', function() {
|
|
const onLateError = jasmine.createSpy('onLateError');
|
|
const suite = new privateUnderTest.Suite({
|
|
onLateError
|
|
});
|
|
const error = new Error('oops');
|
|
|
|
suite.handleException(error);
|
|
|
|
expect(onLateError).not.toHaveBeenCalled();
|
|
expect(suite.doneEvent().failedExpectations.length).toEqual(1);
|
|
});
|
|
|
|
it('clears the reportedDone flag when reset', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
queueableFn: { fn: function() {} }
|
|
});
|
|
suite.reportedDone = true;
|
|
|
|
suite.reset();
|
|
|
|
expect(suite.reportedDone).toBeFalse();
|
|
});
|
|
|
|
it('calls timer to compute duration', function() {
|
|
const suite = new privateUnderTest.Suite({
|
|
env: env,
|
|
id: 456,
|
|
description: 'I am a suite',
|
|
timer: jasmine.createSpyObj('timer', { start: null, elapsed: 77000 })
|
|
});
|
|
suite.startTimer();
|
|
suite.endTimer();
|
|
expect(suite.doneEvent().duration).toEqual(77000);
|
|
});
|
|
|
|
describe('#sharedUserContext', function() {
|
|
beforeEach(function() {
|
|
this.suite = new privateUnderTest.Suite({});
|
|
});
|
|
|
|
it('returns a UserContext', function() {
|
|
expect(this.suite.sharedUserContext().constructor).toBe(
|
|
privateUnderTest.UserContext
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('attr.autoCleanClosures', function() {
|
|
function arrangeSuite(attrs) {
|
|
const suite = new privateUnderTest.Suite(attrs);
|
|
suite.beforeAll(function() {});
|
|
suite.beforeEach(function() {});
|
|
suite.afterEach(function() {});
|
|
suite.afterAll(function() {});
|
|
return suite;
|
|
}
|
|
|
|
it('should clean closures when "attr.autoCleanClosures" is missing', function() {
|
|
const suite = arrangeSuite({});
|
|
suite.cleanupBeforeAfter();
|
|
expect(suite.beforeAllFns[0].fn).toBe(null);
|
|
expect(suite.beforeFns[0].fn).toBe(null);
|
|
expect(suite.afterFns[0].fn).toBe(null);
|
|
expect(suite.afterAllFns[0].fn).toBe(null);
|
|
});
|
|
|
|
it('should clean closures when "attr.autoCleanClosures" is true', function() {
|
|
const suite = arrangeSuite({ autoCleanClosures: true });
|
|
suite.cleanupBeforeAfter();
|
|
expect(suite.beforeAllFns[0].fn).toBe(null);
|
|
expect(suite.beforeFns[0].fn).toBe(null);
|
|
expect(suite.afterFns[0].fn).toBe(null);
|
|
expect(suite.afterAllFns[0].fn).toBe(null);
|
|
});
|
|
|
|
it('should NOT clean closures when "attr.autoCleanClosures" is false', function() {
|
|
const suite = arrangeSuite({ autoCleanClosures: false });
|
|
suite.cleanupBeforeAfter();
|
|
expect(suite.beforeAllFns[0].fn).not.toBe(null);
|
|
expect(suite.beforeFns[0].fn).not.toBe(null);
|
|
expect(suite.afterFns[0].fn).not.toBe(null);
|
|
expect(suite.afterAllFns[0].fn).not.toBe(null);
|
|
});
|
|
});
|
|
|
|
describe('#reset', function() {
|
|
it('should reset the "pending" status', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
suite.pend();
|
|
suite.reset();
|
|
expect(suite.doneEvent().status).toBe('passed');
|
|
});
|
|
|
|
it('should not reset the "pending" status when the suite was excluded', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
suite.exclude();
|
|
suite.reset();
|
|
expect(suite.doneEvent().status).toBe('pending');
|
|
});
|
|
|
|
it('should also reset the children', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
const child1 = jasmine.createSpyObj(['reset']);
|
|
const child2 = jasmine.createSpyObj(['reset']);
|
|
suite.addChild(child1);
|
|
suite.addChild(child2);
|
|
|
|
suite.reset();
|
|
|
|
expect(child1.reset).toHaveBeenCalled();
|
|
expect(child2.reset).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should reset the failedExpectations', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
suite.handleException(new Error());
|
|
|
|
suite.reset();
|
|
|
|
const result = suite.doneEvent();
|
|
expect(result.status).toBe('passed');
|
|
expect(result.failedExpectations).toHaveSize(0);
|
|
});
|
|
});
|
|
|
|
describe('#onMultipleDone', function() {
|
|
it('reports a special error when it is the top suite', function() {
|
|
const onLateError = jasmine.createSpy('onLateError');
|
|
const suite = new privateUnderTest.Suite({
|
|
onLateError,
|
|
parentSuite: null
|
|
});
|
|
|
|
suite.onMultipleDone();
|
|
|
|
expect(onLateError).toHaveBeenCalledTimes(1);
|
|
expect(onLateError.calls.argsFor(0)[0]).toBeInstanceOf(Error);
|
|
expect(onLateError.calls.argsFor(0)[0].message).toEqual(
|
|
'A top-level beforeAll or afterAll function called its ' +
|
|
"'done' callback more than once."
|
|
);
|
|
});
|
|
|
|
it('reports an error including the suite name when it is a normal suite', function() {
|
|
const onLateError = jasmine.createSpy('onLateError');
|
|
const suite = new privateUnderTest.Suite({
|
|
onLateError,
|
|
description: 'the suite',
|
|
parentSuite: {
|
|
description: 'the parent suite',
|
|
parentSuite: {}
|
|
}
|
|
});
|
|
|
|
suite.onMultipleDone();
|
|
|
|
expect(onLateError).toHaveBeenCalledTimes(1);
|
|
expect(onLateError.calls.argsFor(0)[0]).toBeInstanceOf(Error);
|
|
expect(onLateError.calls.argsFor(0)[0].message).toEqual(
|
|
"An asynchronous beforeAll or afterAll function called its 'done' " +
|
|
'callback more than once.\n(in suite: the parent suite the suite)'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('#hasChildWithDescription', function() {
|
|
it('returns true if there is a child with the given description', function() {
|
|
const subject = new privateUnderTest.Suite({});
|
|
const description = 'a spec';
|
|
subject.addChild({ description });
|
|
|
|
expect(subject.hasChildWithDescription(description)).toBeTrue();
|
|
});
|
|
|
|
it('returns false if there is no child with the given description', function() {
|
|
const subject = new privateUnderTest.Suite({});
|
|
subject.addChild({ description: 'a different spec' });
|
|
|
|
expect(subject.hasChildWithDescription('a spec')).toBeFalse();
|
|
});
|
|
|
|
it('does not recurse into child suites', function() {
|
|
const subject = new privateUnderTest.Suite({});
|
|
const childSuite = new privateUnderTest.Suite({});
|
|
subject.addChild(childSuite);
|
|
const description = 'a spec';
|
|
childSuite.addChild(description);
|
|
|
|
expect(subject.hasChildWithDescription('a spec')).toBeFalse();
|
|
});
|
|
});
|
|
|
|
describe('#setSuiteProperty', function() {
|
|
it('throws if the key is not a string', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
|
|
expect(function() {
|
|
suite.setSuiteProperty({}, '');
|
|
}).toThrowError('Key must be a string');
|
|
});
|
|
|
|
it('throws if the value is not structured-cloneable', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
|
|
expect(function() {
|
|
suite.setSuiteProperty('k', new Promise(() => {}));
|
|
}).toThrowError("Value can't be cloned");
|
|
});
|
|
|
|
it('throws if the value is not JSON-serializable', function() {
|
|
const suite = new privateUnderTest.Suite({});
|
|
|
|
expect(function() {
|
|
const v = {};
|
|
v.self = v;
|
|
suite.setSuiteProperty('k', v);
|
|
}).toThrowError("Value can't be cloned");
|
|
});
|
|
});
|
|
|
|
describe('#startedEvent', function() {
|
|
it('includes only properties that are known before execution', function() {
|
|
const topSuite = new privateUnderTest.Suite({});
|
|
const parentSuite = new privateUnderTest.Suite({
|
|
id: 'suite1',
|
|
parentSuite: topSuite,
|
|
description: 'a parent suite'
|
|
});
|
|
const suite = new privateUnderTest.Suite({
|
|
id: 'suite2',
|
|
parentSuite,
|
|
reportedParentSuiteId: parentSuite.id,
|
|
description: 'a suite',
|
|
filename: 'somefile.js',
|
|
getPath() {
|
|
return ['a parent suite', 'a spec'];
|
|
},
|
|
queueableFn: { fn: () => {} }
|
|
});
|
|
|
|
expect(suite.startedEvent()).toEqual({
|
|
id: 'suite2',
|
|
parentSuiteId: 'suite1',
|
|
description: 'a suite',
|
|
fullName: 'a parent suite a suite',
|
|
filename: 'somefile.js'
|
|
});
|
|
});
|
|
});
|
|
});
|