Report the ID of each suite/spec's parent
This is intended to support parallel execution, which is planned for a future release of Jasmine. Because the execution of unrelated suites will interleave when run in parallel, reporters will not be able to assume that the most recent `suiteStarted` event identifies the parent of the current suite/spec. By adding this feature now, we allow reporters to support both parallel execution and at least some 4.x versions without having to implement two different ways of finding the parent suite.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
Copyright (c) 2008-2023 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -742,6 +742,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
this.resultCallback = attrs.resultCallback || function() {};
|
||||
this.id = attrs.id;
|
||||
this.filename = attrs.filename;
|
||||
this.parentSuiteId = attrs.parentSuiteId;
|
||||
this.description = attrs.description || '';
|
||||
this.queueableFn = attrs.queueableFn;
|
||||
this.beforeAndAfterFns =
|
||||
@@ -890,6 +891,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
* @property {String} id - The unique id of this spec.
|
||||
* @property {String} description - The description passed to the {@link it} that created this spec.
|
||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||
* @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
|
||||
* @property {String} filename - The name of the file the spec was defined in.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
||||
@@ -905,6 +907,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
fullName: this.getFullName(),
|
||||
parentSuiteId: this.parentSuiteId,
|
||||
filename: this.filename,
|
||||
failedExpectations: [],
|
||||
passedExpectations: [],
|
||||
@@ -9533,6 +9536,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
this.id = attrs.id;
|
||||
this.parentSuite = attrs.parentSuite;
|
||||
this.description = attrs.description;
|
||||
this.reportedParentSuiteId = attrs.reportedParentSuiteId;
|
||||
this.filename = attrs.filename;
|
||||
this.expectationFactory = attrs.expectationFactory;
|
||||
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
|
||||
@@ -9639,6 +9643,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
* @property {String} id - The unique id of this suite.
|
||||
* @property {String} description - The description text passed to the {@link describe} that made this suite.
|
||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||
* @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
|
||||
* @property {String} filename - The name of the file the suite was defined in.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
||||
@@ -9651,6 +9656,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
fullName: this.getFullName(),
|
||||
parentSuiteId: this.reportedParentSuiteId,
|
||||
filename: this.filename,
|
||||
failedExpectations: [],
|
||||
deprecationWarnings: [],
|
||||
@@ -10018,11 +10024,15 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
|
||||
|
||||
suiteFactory_(description, filename) {
|
||||
const config = this.env_.configuration();
|
||||
const parentSuite = this.currentDeclarationSuite_;
|
||||
const reportedParentSuiteId =
|
||||
parentSuite === this.topSuite ? null : parentSuite.id;
|
||||
return new j$.Suite({
|
||||
id: 'suite' + this.nextSuiteId_++,
|
||||
description,
|
||||
filename,
|
||||
parentSuite: this.currentDeclarationSuite_,
|
||||
parentSuite,
|
||||
reportedParentSuiteId,
|
||||
timer: new j$.Timer(),
|
||||
expectationFactory: this.expectationFactory_,
|
||||
asyncExpectationFactory: this.suiteAsyncExpectationFactory_,
|
||||
@@ -10058,9 +10068,11 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
|
||||
this.totalSpecsDefined++;
|
||||
const config = this.env_.configuration();
|
||||
const suite = this.currentDeclarationSuite_;
|
||||
const parentSuiteId = suite === this.topSuite ? null : suite.id;
|
||||
const spec = new j$.Spec({
|
||||
id: 'spec' + this.nextSpecId_++,
|
||||
filename,
|
||||
parentSuiteId,
|
||||
beforeAndAfterFns: beforeAndAfterFns(suite),
|
||||
expectationFactory: this.expectationFactory_,
|
||||
asyncExpectationFactory: this.specAsyncExpectationFactory_,
|
||||
|
||||
@@ -195,6 +195,7 @@ describe('Spec', function() {
|
||||
onStart: startCallback,
|
||||
resultCallback: resultCallback,
|
||||
description: 'with a spec',
|
||||
parentSuiteId: 'suite1',
|
||||
filename: 'someSpecFile.js',
|
||||
getSpecName: function() {
|
||||
return 'a suite with a spec';
|
||||
@@ -220,6 +221,7 @@ describe('Spec', function() {
|
||||
status: 'pending',
|
||||
description: 'with a spec',
|
||||
fullName: 'a suite with a spec',
|
||||
parentSuiteId: 'suite1',
|
||||
filename: 'someSpecFile.js',
|
||||
failedExpectations: [],
|
||||
passedExpectations: [],
|
||||
|
||||
@@ -1933,11 +1933,17 @@ describe('Env integration', function() {
|
||||
'specStarted',
|
||||
'specDone'
|
||||
]);
|
||||
const suiteFullNameToId = {};
|
||||
reporter.suiteStarted.and.callFake(function(e) {
|
||||
suiteFullNameToId[e.fullName] = e.id;
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.it('a top level spec', function() {});
|
||||
|
||||
env.describe('A Suite', function() {
|
||||
env.it('with a top level spec', function() {
|
||||
env.it('with a spec', function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.describe('with a nested suite', function() {
|
||||
@@ -1960,37 +1966,109 @@ describe('Env integration', function() {
|
||||
await env.execute();
|
||||
|
||||
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
|
||||
totalSpecsDefined: 5,
|
||||
totalSpecsDefined: 6,
|
||||
order: jasmine.any(jasmineUnderTest.Order)
|
||||
});
|
||||
|
||||
expect(reporter.specDone.calls.count()).toBe(5);
|
||||
expect(reporter.specStarted.calls.count()).toBe(6);
|
||||
expect(reporter.specDone.calls.count()).toBe(6);
|
||||
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a top level spec',
|
||||
status: 'passed'
|
||||
description: 'a top level spec',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: "with an x'ed spec",
|
||||
status: 'pending'
|
||||
description: 'a top level spec',
|
||||
status: 'passed',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a spec',
|
||||
parentSuiteId: suiteFullNameToId['A Suite']
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a spec',
|
||||
status: 'failed'
|
||||
status: 'passed',
|
||||
parentSuiteId: suiteFullNameToId['A Suite']
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: "with an x'ed spec",
|
||||
parentSuiteId: suiteFullNameToId['A Suite with a nested suite']
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: "with an x'ed spec",
|
||||
status: 'pending',
|
||||
parentSuiteId: suiteFullNameToId['A Suite with a nested suite']
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a spec',
|
||||
parentSuiteId: suiteFullNameToId['A Suite with a nested suite']
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a spec',
|
||||
status: 'failed',
|
||||
parentSuiteId: suiteFullNameToId['A Suite with a nested suite']
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'is pending',
|
||||
parentSuiteId:
|
||||
suiteFullNameToId['A Suite with only non-executable specs']
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'is pending',
|
||||
status: 'pending'
|
||||
status: 'pending',
|
||||
parentSuiteId:
|
||||
suiteFullNameToId['A Suite with only non-executable specs']
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.suiteStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'A Suite',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'A Suite',
|
||||
status: 'passed',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.suiteStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a nested suite',
|
||||
parentSuiteId: suiteFullNameToId['A Suite']
|
||||
})
|
||||
);
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'with a nested suite',
|
||||
status: 'passed',
|
||||
parentSuiteId: suiteFullNameToId['A Suite']
|
||||
})
|
||||
);
|
||||
|
||||
@@ -2001,6 +2079,89 @@ describe('Env integration', function() {
|
||||
expect(suiteResult.description).toEqual('A Suite');
|
||||
});
|
||||
|
||||
it('reports focused specs and suites as expected', async function() {
|
||||
const reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
'suiteStarted',
|
||||
'suiteDone',
|
||||
'specStarted',
|
||||
'specDone'
|
||||
]);
|
||||
const suiteFullNameToId = {};
|
||||
reporter.suiteStarted.and.callFake(function(e) {
|
||||
suiteFullNameToId[e.fullName] = e.id;
|
||||
});
|
||||
|
||||
env.fit('a focused top level spec', function() {});
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.fdescribe('a focused suite', function() {
|
||||
env.fit('a focused spec', function() {});
|
||||
});
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
await env.execute();
|
||||
|
||||
expect(reporter.specStarted).toHaveBeenCalledTimes(2);
|
||||
expect(reporter.specDone).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a focused top level spec',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a focused top level spec',
|
||||
status: 'passed',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.specStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a focused spec',
|
||||
parentSuiteId: suiteFullNameToId['a suite a focused suite']
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a focused spec',
|
||||
status: 'passed',
|
||||
parentSuiteId: suiteFullNameToId['a suite a focused suite']
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.suiteStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a suite',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a suite',
|
||||
status: 'passed',
|
||||
parentSuiteId: null
|
||||
})
|
||||
);
|
||||
|
||||
expect(reporter.suiteStarted).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a focused suite',
|
||||
parentSuiteId: suiteFullNameToId['a suite']
|
||||
})
|
||||
);
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
description: 'a focused suite',
|
||||
status: 'passed',
|
||||
parentSuiteId: suiteFullNameToId['a suite']
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should report the random seed at the beginning and end of execution', async function() {
|
||||
const reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
'jasmineStarted',
|
||||
|
||||
@@ -5,6 +5,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
this.resultCallback = attrs.resultCallback || function() {};
|
||||
this.id = attrs.id;
|
||||
this.filename = attrs.filename;
|
||||
this.parentSuiteId = attrs.parentSuiteId;
|
||||
this.description = attrs.description || '';
|
||||
this.queueableFn = attrs.queueableFn;
|
||||
this.beforeAndAfterFns =
|
||||
@@ -153,6 +154,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
* @property {String} id - The unique id of this spec.
|
||||
* @property {String} description - The description passed to the {@link it} that created this spec.
|
||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||
* @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
|
||||
* @property {String} filename - The name of the file the spec was defined in.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
||||
@@ -168,6 +170,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
fullName: this.getFullName(),
|
||||
parentSuiteId: this.parentSuiteId,
|
||||
filename: this.filename,
|
||||
failedExpectations: [],
|
||||
passedExpectations: [],
|
||||
|
||||
@@ -4,6 +4,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
this.id = attrs.id;
|
||||
this.parentSuite = attrs.parentSuite;
|
||||
this.description = attrs.description;
|
||||
this.reportedParentSuiteId = attrs.reportedParentSuiteId;
|
||||
this.filename = attrs.filename;
|
||||
this.expectationFactory = attrs.expectationFactory;
|
||||
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
|
||||
@@ -110,6 +111,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
* @property {String} id - The unique id of this suite.
|
||||
* @property {String} description - The description text passed to the {@link describe} that made this suite.
|
||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||
* @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
|
||||
* @property {String} filename - The name of the file the suite was defined in.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
||||
@@ -122,6 +124,7 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
fullName: this.getFullName(),
|
||||
parentSuiteId: this.reportedParentSuiteId,
|
||||
filename: this.filename,
|
||||
failedExpectations: [],
|
||||
deprecationWarnings: [],
|
||||
|
||||
@@ -161,11 +161,15 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
|
||||
|
||||
suiteFactory_(description, filename) {
|
||||
const config = this.env_.configuration();
|
||||
const parentSuite = this.currentDeclarationSuite_;
|
||||
const reportedParentSuiteId =
|
||||
parentSuite === this.topSuite ? null : parentSuite.id;
|
||||
return new j$.Suite({
|
||||
id: 'suite' + this.nextSuiteId_++,
|
||||
description,
|
||||
filename,
|
||||
parentSuite: this.currentDeclarationSuite_,
|
||||
parentSuite,
|
||||
reportedParentSuiteId,
|
||||
timer: new j$.Timer(),
|
||||
expectationFactory: this.expectationFactory_,
|
||||
asyncExpectationFactory: this.suiteAsyncExpectationFactory_,
|
||||
@@ -201,9 +205,11 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
|
||||
this.totalSpecsDefined++;
|
||||
const config = this.env_.configuration();
|
||||
const suite = this.currentDeclarationSuite_;
|
||||
const parentSuiteId = suite === this.topSuite ? null : suite.id;
|
||||
const spec = new j$.Spec({
|
||||
id: 'spec' + this.nextSpecId_++,
|
||||
filename,
|
||||
parentSuiteId,
|
||||
beforeAndAfterFns: beforeAndAfterFns(suite),
|
||||
expectationFactory: this.expectationFactory_,
|
||||
asyncExpectationFactory: this.specAsyncExpectationFactory_,
|
||||
|
||||
Reference in New Issue
Block a user