Backfill some unit tests for Runner's interaction with TreeProcessor
This commit is contained in:
@@ -1663,6 +1663,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
runableResources,
|
||||
reporter,
|
||||
queueRunnerFactory,
|
||||
TreeProcessor: j$.TreeProcessor,
|
||||
getConfig: () => config,
|
||||
reportSpecDone
|
||||
});
|
||||
@@ -9284,6 +9285,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
||||
this.focusedRunables_ = options.focusedRunables;
|
||||
this.runableResources_ = options.runableResources;
|
||||
this.queueRunnerFactory_ = options.queueRunnerFactory;
|
||||
this.TreeProcessor_ = options.TreeProcessor;
|
||||
this.reporter_ = options.reporter;
|
||||
this.getConfig_ = options.getConfig;
|
||||
this.reportSpecDone_ = options.reportSpecDone;
|
||||
@@ -9331,7 +9333,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
||||
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
|
||||
});
|
||||
|
||||
const processor = new j$.TreeProcessor({
|
||||
const processor = new this.TreeProcessor_({
|
||||
tree: this.topSuite_,
|
||||
runnableIds: runablesToRun,
|
||||
queueRunnerFactory: options => {
|
||||
|
||||
272
spec/core/RunnerSpec.js
Normal file
272
spec/core/RunnerSpec.js
Normal file
@@ -0,0 +1,272 @@
|
||||
describe('Runner', function() {
|
||||
describe('TreeProcessor nodeComplete callback', function() {
|
||||
it('throws if the wrong suite is passed to nodeComplete', async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
startTimer: () => {}
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
|
||||
expect(function() {
|
||||
const someOtherSuite = {};
|
||||
treeProcessorOpts.nodeComplete(someOtherSuite, {}, () => {});
|
||||
}).toThrowError('Tried to complete the wrong suite');
|
||||
});
|
||||
|
||||
it("ends the suite's timer", async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
startTimer: () => {},
|
||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
await callWithNext(treeProcessorOpts.nodeComplete, [suiteToRun, {}]);
|
||||
|
||||
expect(suiteToRun.endTimer).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sets hasFailures to true when the suite fails', async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
startTimer: () => {},
|
||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
||||
suiteToRun,
|
||||
{ status: 'failed' }
|
||||
]);
|
||||
|
||||
expect(subject.hasFailures).toBe(true);
|
||||
});
|
||||
|
||||
it('does not set hasFailures to true when the suite passes', async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
startTimer: () => {},
|
||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
||||
suiteToRun,
|
||||
{ status: 'passed' }
|
||||
]);
|
||||
|
||||
expect(subject.hasFailures).toBe(false);
|
||||
});
|
||||
|
||||
it('does not set hasFailures to false when the suite passes', async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
subject.hasFailures = true;
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
startTimer: () => {},
|
||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
||||
suiteToRun,
|
||||
{ status: 'passed' }
|
||||
]);
|
||||
|
||||
expect(subject.hasFailures).toBe(true);
|
||||
});
|
||||
|
||||
describe('reporting', function() {
|
||||
it('reports the suiteDone event', async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const reporter = spyReporter();
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor,
|
||||
reporter
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
startTimer: () => {},
|
||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
||||
suiteToRun,
|
||||
{ status: 'passed' }
|
||||
]);
|
||||
|
||||
expect(reporter.suiteDone).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when the suite had a beforeAll failure', function() {
|
||||
it('reports children before the suiteDone event', async function() {
|
||||
const TreeProcessor = spyTreeProcessorCtor();
|
||||
const reporter = spyReporter();
|
||||
const reportSpecDone = jasmine
|
||||
.createSpy('reportSpecDone')
|
||||
.and.callFake(function(child, result, next) {
|
||||
next();
|
||||
});
|
||||
const subject = new jasmineUnderTest.Runner({
|
||||
...defaultCtorOptions(),
|
||||
TreeProcessor,
|
||||
reporter,
|
||||
reportSpecDone
|
||||
});
|
||||
|
||||
const promise = subject.execute();
|
||||
expect(TreeProcessor).toHaveBeenCalled();
|
||||
await checkImmediateRejection(promise);
|
||||
|
||||
const treeProcessorOpts = TreeProcessor.calls.argsFor(0)[0];
|
||||
const suiteToRun = {
|
||||
parentSuite: stubSuite(),
|
||||
children: [
|
||||
{
|
||||
result: { description: 'a spec' },
|
||||
addExpectationResult: jasmine.createSpy('addExpectationResult')
|
||||
}
|
||||
],
|
||||
startTimer: () => {},
|
||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||
};
|
||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
||||
|
||||
suiteToRun.hadBeforeAllFailure = true;
|
||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
||||
suiteToRun,
|
||||
{ status: 'passed' }
|
||||
]);
|
||||
|
||||
expect(
|
||||
suiteToRun.children[0].addExpectationResult
|
||||
).toHaveBeenCalledWith(
|
||||
false,
|
||||
{
|
||||
passed: false,
|
||||
message:
|
||||
'Not run because a beforeAll function failed. The beforeAll failure will be reported on the suite that caused it.'
|
||||
},
|
||||
true
|
||||
);
|
||||
expect(
|
||||
suiteToRun.children[0].addExpectationResult
|
||||
).toHaveBeenCalledBefore(reportSpecDone);
|
||||
expect(reportSpecDone).toHaveBeenCalledBefore(reporter.suiteDone);
|
||||
expect(reporter.specStarted).toHaveBeenCalledBefore(reportSpecDone);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function callWithNext(fn, args) {
|
||||
let next;
|
||||
const nextPromise = new Promise(function(resolve) {
|
||||
next = resolve;
|
||||
});
|
||||
fn.apply(null, [...args, next]);
|
||||
await nextPromise;
|
||||
}
|
||||
|
||||
// Check whether promise has already been rejected
|
||||
async function checkImmediateRejection(promise) {
|
||||
await Promise.race([promise, Promise.resolve()]);
|
||||
}
|
||||
|
||||
function spyTreeProcessorCtor() {
|
||||
return jasmine.createSpy('TreeProcessor ctor').and.returnValue({
|
||||
execute: () => {},
|
||||
processTree: () => ({ valid: true })
|
||||
});
|
||||
}
|
||||
|
||||
function spyReporter() {
|
||||
return jasmine.createSpyObj('reporter', {
|
||||
jasmineStarted: Promise.resolve(),
|
||||
jasmineDone: Promise.resolve(),
|
||||
suiteStarted: Promise.resolve(),
|
||||
suiteDone: Promise.resolve(),
|
||||
specStarted: Promise.resolve(),
|
||||
specDone: Promise.resolve()
|
||||
});
|
||||
}
|
||||
|
||||
function defaultCtorOptions() {
|
||||
return {
|
||||
topSuite: stubSuite(),
|
||||
runableResources: {
|
||||
initForRunable: () => {},
|
||||
clearForRunable: () => {}
|
||||
},
|
||||
reporter: spyReporter(),
|
||||
focusedRunables: () => [],
|
||||
getConfig: () => ({}),
|
||||
totalSpecsDefined: () => 1
|
||||
};
|
||||
}
|
||||
|
||||
function stubSuite() {
|
||||
return {
|
||||
result: {
|
||||
failedExpectations: []
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -497,6 +497,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
runableResources,
|
||||
reporter,
|
||||
queueRunnerFactory,
|
||||
TreeProcessor: j$.TreeProcessor,
|
||||
getConfig: () => config,
|
||||
reportSpecDone
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
||||
this.focusedRunables_ = options.focusedRunables;
|
||||
this.runableResources_ = options.runableResources;
|
||||
this.queueRunnerFactory_ = options.queueRunnerFactory;
|
||||
this.TreeProcessor_ = options.TreeProcessor;
|
||||
this.reporter_ = options.reporter;
|
||||
this.getConfig_ = options.getConfig;
|
||||
this.reportSpecDone_ = options.reportSpecDone;
|
||||
@@ -54,7 +55,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
||||
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
|
||||
});
|
||||
|
||||
const processor = new j$.TreeProcessor({
|
||||
const processor = new this.TreeProcessor_({
|
||||
tree: this.topSuite_,
|
||||
runnableIds: runablesToRun,
|
||||
queueRunnerFactory: options => {
|
||||
|
||||
Reference in New Issue
Block a user