Update and move remaining disabled Runner specs

This commit is contained in:
Steve Gravrock
2025-08-28 06:55:20 -07:00
parent 6449832e7e
commit 4b7d5e3623
2 changed files with 241 additions and 279 deletions

View File

@@ -1,229 +1,4 @@
describe('Runner', function() {
// TODO: Update and re-enable these once things stabilize
xdescribe('TreeProcessor suiteSegmentComplete callback', function() {
it('throws if the wrong suite is passed to suiteSegmentComplete', 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.suiteSegmentStart, [suiteToRun]);
expect(function() {
const someOtherSuite = {};
treeProcessorOpts.suiteSegmentComplete(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.suiteSegmentStart, [suiteToRun]);
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
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.suiteSegmentStart, [suiteToRun]);
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
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.suiteSegmentStart, [suiteToRun]);
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
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.suiteSegmentStart, [suiteToRun]);
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
suiteToRun,
{ status: 'passed' }
]);
expect(subject.hasFailures).toBe(true);
});
describe('reporting', function() {
it('reports the suiteDone event', async function() {
const TreeProcessor = spyTreeProcessorCtor();
const reportDispatcher = spyReporter();
const subject = new jasmineUnderTest.Runner({
...defaultCtorOptions(),
TreeProcessor,
reportDispatcher
});
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.suiteSegmentStart, [suiteToRun]);
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
suiteToRun,
{ status: 'passed' }
]);
expect(reportDispatcher.suiteDone).toHaveBeenCalled();
});
describe('when the suite had a beforeAll failure', function() {
it('reports children before the suiteDone event', async function() {
const TreeProcessor = spyTreeProcessorCtor();
const reportDispatcher = spyReporter();
const reportSpecDone = jasmine
.createSpy('reportSpecDone')
.and.callFake(function(child, result, next) {
next();
});
const subject = new jasmineUnderTest.Runner({
...defaultCtorOptions(),
TreeProcessor,
reportDispatcher,
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.suiteSegmentStart, [suiteToRun]);
suiteToRun.hadBeforeAllFailure = true;
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
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(
reportDispatcher.suiteDone
);
expect(reportDispatcher.specStarted).toHaveBeenCalledBefore(
reportSpecDone
);
});
});
});
});
describe('Integration with TreeProcessor and TreeRunner', function() {
let suiteNumber,
specNumber,
@@ -852,58 +627,4 @@ describe('Runner', function() {
await expectAsync(promise).toBePending();
});
});
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('reportDispatcher', {
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: () => {}
},
reportDispatcher: spyReporter(),
focusedRunables: () => [],
getConfig: () => ({}),
totalSpecsDefined: () => 1
};
}
function stubSuite() {
return {
result: {
failedExpectations: []
}
};
}
});

View File

@@ -270,6 +270,247 @@ describe('TreeRunner', function() {
}
});
describe('Suite execution', function() {
it('reports the duration of the suite', async function() {
const timer = jasmine.createSpyObj('timer', ['start', 'elapsed']);
const topSuite = new jasmineUnderTest.Suite({ id: 'topSuite' });
const suite = new jasmineUnderTest.Suite({
id: 'suite1',
parentSuite: topSuite,
timer
});
topSuite.addChild(suite);
const executionTree = {
topSuite,
childrenOfTopSuite() {
return [{ suite }];
},
childrenOfSuiteSegment() {
return [];
},
isExcluded() {
return false;
}
};
const runQueue = jasmine.createSpy('runQueue');
const reportDispatcher = mockReportDispatcher();
const subject = new jasmineUnderTest.TreeRunner({
executionTree,
runQueue,
globalErrors: mockGlobalErrors(),
runableResources: mockRunableResources(),
reportDispatcher,
currentRunableTracker: new jasmineUnderTest.CurrentRunableTracker(),
getConfig() {
return {};
},
reportChildrenOfBeforeAllFailure() {}
});
const executePromise = subject.execute();
expect(runQueue).toHaveBeenCalledTimes(1);
const topSuiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
runQueue.calls.reset();
topSuiteRunQueueOpts.queueableFns[0].fn(function() {});
expect(runQueue).toHaveBeenCalledTimes(1);
expect(timer.start).not.toHaveBeenCalled();
const suiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
suiteRunQueueOpts.queueableFns[0].fn();
expect(timer.start).toHaveBeenCalled();
expect(timer.elapsed).not.toHaveBeenCalled();
timer.elapsed.and.returnValue('the duration');
suiteRunQueueOpts.onComplete();
expect(timer.elapsed).toHaveBeenCalled();
const result = suite.getResult();
expect(result.duration).toEqual('the duration');
expect(reportDispatcher.suiteDone).toHaveBeenCalledWith(result);
await expectAsync(executePromise).toBePending();
});
it('returns false if a suite failed', async function() {
const topSuite = new jasmineUnderTest.Suite({ id: 'topSuite' });
const failingSuite = new jasmineUnderTest.Suite({
id: 'failingSuite',
parentSuite: topSuite
});
const passingSuite = new jasmineUnderTest.Suite({
id: 'passingSuite',
parentSuite: topSuite
});
const executionTree = {
topSuite,
childrenOfTopSuite() {
return [{ suite: failingSuite }, { suite: passingSuite }];
},
childrenOfSuiteSegment() {
return [];
},
isExcluded() {
return false;
}
};
const runQueue = jasmine.createSpy('runQueue');
const reportDispatcher = mockReportDispatcher();
const subject = new jasmineUnderTest.TreeRunner({
executionTree,
runQueue,
globalErrors: mockGlobalErrors(),
runableResources: mockRunableResources(),
reportDispatcher,
currentRunableTracker: new jasmineUnderTest.CurrentRunableTracker(),
getConfig() {
return {};
},
reportChildrenOfBeforeAllFailure() {}
});
const executePromise = subject.execute();
expect(runQueue).toHaveBeenCalledTimes(1);
const topSuiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
runQueue.calls.reset();
topSuiteRunQueueOpts.queueableFns[0].fn(function() {});
// Fail the first suite.
expect(runQueue).toHaveBeenCalledTimes(1);
const failingSuiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
runQueue.calls.reset();
failingSuiteRunQueueOpts.queueableFns[0].fn();
failingSuite.addExpectationResult(false, {});
failingSuiteRunQueueOpts.onComplete();
// Passing the second suite should not reset the overall result.
topSuiteRunQueueOpts.queueableFns[1].fn(function() {});
expect(runQueue).toHaveBeenCalledTimes(1);
const passingSuiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
passingSuiteRunQueueOpts.queueableFns[0].fn();
passingSuiteRunQueueOpts.onComplete();
topSuiteRunQueueOpts.onComplete();
const result = await executePromise;
expect(result.hasFailures).toEqual(true);
});
it('reports children when there is a beforeAll failure', async function() {
const topSuite = new jasmineUnderTest.Suite({ id: 'topSuite' });
const suite = new jasmineUnderTest.Suite({
id: 'suite',
parentSuite: topSuite
});
suite.beforeAll({ fn() {} });
const spec = new jasmineUnderTest.Spec({
id: 'spec',
parentSuite: suite,
queueableFn: { fn() {} }
});
const executionTree = {
topSuite,
childrenOfTopSuite() {
return [{ suite }];
},
childrenOfSuiteSegment() {
return [{ spec }];
},
isExcluded() {
return false;
}
};
const runQueue = jasmine.createSpy('runQueue');
const reportDispatcher = mockReportDispatcher();
const reportChildrenOfBeforeAllFailure = jasmine
.createSpy('reportChildrenOfBeforeAllFailure')
.and.returnValue(Promise.resolve());
const subject = new jasmineUnderTest.TreeRunner({
executionTree,
runQueue,
globalErrors: mockGlobalErrors(),
runableResources: mockRunableResources(),
reportDispatcher,
currentRunableTracker: new jasmineUnderTest.CurrentRunableTracker(),
reportChildrenOfBeforeAllFailure,
getConfig() {
return {};
}
});
const executePromise = subject.execute();
expect(runQueue).toHaveBeenCalledTimes(1);
const topSuiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
runQueue.calls.reset();
topSuiteRunQueueOpts.queueableFns[0].fn(function() {});
expect(runQueue).toHaveBeenCalledTimes(1);
const suiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
suiteRunQueueOpts.queueableFns[0].fn();
suite.hadBeforeAllFailure = true;
suiteRunQueueOpts.onComplete();
await Promise.resolve();
expect(reportChildrenOfBeforeAllFailure).toHaveBeenCalledBefore(
reportDispatcher.suiteDone
);
await expectAsync(executePromise).toBePending();
});
it('throws if the wrong suite is completed', async function() {
const topSuite = new jasmineUnderTest.Suite({ id: 'topSuite' });
const suite = new jasmineUnderTest.Suite({
id: 'suite',
parentSuite: topSuite
});
const spec = new jasmineUnderTest.Spec({
id: 'spec',
parentSuite: suite,
queueableFn: { fn() {} }
});
const executionTree = {
topSuite,
childrenOfTopSuite() {
return [{ suite }];
},
childrenOfSuiteSegment() {
return [{ spec }];
},
isExcluded() {
return false;
}
};
const runQueue = jasmine.createSpy('runQueue');
const reportDispatcher = mockReportDispatcher();
const subject = new jasmineUnderTest.TreeRunner({
executionTree,
runQueue,
globalErrors: mockGlobalErrors(),
runableResources: mockRunableResources(),
reportDispatcher,
currentRunableTracker: new jasmineUnderTest.CurrentRunableTracker(),
getConfig() {
return {};
},
reportChildrenOfBeforeAllFailure() {}
});
const executePromise = subject.execute();
expect(runQueue).toHaveBeenCalledTimes(1);
const topSuiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
runQueue.calls.reset();
topSuiteRunQueueOpts.queueableFns[0].fn(function() {});
expect(runQueue).toHaveBeenCalledTimes(1);
const suiteRunQueueOpts = runQueue.calls.mostRecent().args[0];
// Complete the suite without starting it
expect(function() {
suiteRunQueueOpts.onComplete();
}).toThrowError('Tried to complete the wrong suite');
await expectAsync(executePromise).toBePending();
});
});
function mockReportDispatcher() {
const reportDispatcher = jasmine.createSpyObj(
'reportDispatcher',