Remove access to non-public properties of suites and specs returned by describe, it, etc.

[#179064612]
This commit is contained in:
Steve Gravrock
2021-07-30 17:36:50 -07:00
parent 6d002d22af
commit 13dfcacbb0
5 changed files with 272 additions and 169 deletions
+99 -83
View File
@@ -663,12 +663,6 @@ getJasmineRequireObj().Spec = function(j$) {
this.expectationFactory = attrs.expectationFactory; this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory; this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
/**
* The unique ID of this spec.
* @name Spec#id
* @readonly
* @type {string}
*/
this.id = attrs.id; this.id = attrs.id;
this.description = attrs.description || ''; this.description = attrs.description || '';
this.queueableFn = attrs.queueableFn; this.queueableFn = attrs.queueableFn;
@@ -898,34 +892,43 @@ getJasmineRequireObj().Spec = function(j$) {
* @interface Spec * @interface Spec
* @see Configuration#specFilter * @see Configuration#specFilter
*/ */
Spec.prototype.buildMetadata = function() { Object.defineProperty(Spec.prototype, 'metadata', {
return { get: function() {
/** if (!this.metadata_) {
* The description passed to the {@link it} that created this spec. this.metadata_ = {
* @name Spec#description /**
* @readonly * The unique ID of this spec.
* @type {string} * @name Spec#id
*/ * @readonly
description: this.description, * @type {string}
*/
id: this.id,
/** /**
* The full description including all ancestors of this spec. * The description passed to the {@link it} that created this spec.
* @name Spec#getFullName * @name Spec#description
* @function * @readonly
* @returns {string} * @type {string}
*/ */
getFullName: this.getFullName.bind(this) description: this.description,
};
}; /**
* The full description including all ancestors of this spec.
* @name Spec#getFullName
* @function
* @returns {string}
*/
getFullName: this.getFullName.bind(this)
};
}
return this.metadata_;
}
});
return Spec; return Spec;
}; };
if (typeof window == void 0 && typeof exports == 'object') {
/* globals exports */
exports.Spec = jasmineRequire.Spec;
}
/*jshint bitwise: false*/ /*jshint bitwise: false*/
getJasmineRequireObj().Order = function() { getJasmineRequireObj().Order = function() {
@@ -1523,7 +1526,7 @@ getJasmineRequireObj().Env = function(j$) {
* @return {Suite} the root suite * @return {Suite} the root suite
*/ */
this.topSuite = function() { this.topSuite = function() {
return topSuite.buildMetadata(null); return topSuite.metadata;
}; };
/** /**
@@ -1906,7 +1909,7 @@ getJasmineRequireObj().Env = function(j$) {
if (suite.parentSuite && !suite.children.length) { if (suite.parentSuite && !suite.children.length) {
throw new Error('describe with no children (describe() or it())'); throw new Error('describe with no children (describe() or it())');
} }
return suite; return suite.metadata;
}; };
this.xdescribe = function(description, specDefinitions) { this.xdescribe = function(description, specDefinitions) {
@@ -1915,7 +1918,7 @@ getJasmineRequireObj().Env = function(j$) {
var suite = suiteFactory(description); var suite = suiteFactory(description);
suite.pend(); suite.pend();
addSpecsToSuite(suite, specDefinitions); addSpecsToSuite(suite, specDefinitions);
return suite; return suite.metadata;
}; };
var focusedRunnables = []; var focusedRunnables = [];
@@ -1930,7 +1933,7 @@ getJasmineRequireObj().Env = function(j$) {
unfocusAncestor(); unfocusAncestor();
addSpecsToSuite(suite, specDefinitions); addSpecsToSuite(suite, specDefinitions);
return suite; return suite.metadata;
}; };
function addSpecsToSuite(suite, specDefinitions) { function addSpecsToSuite(suite, specDefinitions) {
@@ -2020,7 +2023,7 @@ getJasmineRequireObj().Env = function(j$) {
} }
}; };
this.it = function(description, fn, timeout) { this.it_ = function(description, fn, timeout) {
ensureIsNotNested('it'); ensureIsNotNested('it');
// it() sometimes doesn't have a fn argument, so only check the type if // it() sometimes doesn't have a fn argument, so only check the type if
// it's given. // it's given.
@@ -2036,6 +2039,11 @@ getJasmineRequireObj().Env = function(j$) {
return spec; return spec;
}; };
this.it = function(description, fn, timeout) {
const spec = this.it_(description, fn, timeout);
return spec.metadata;
};
this.xit = function(description, fn, timeout) { this.xit = function(description, fn, timeout) {
ensureIsNotNested('xit'); ensureIsNotNested('xit');
// xit(), like it(), doesn't always have a fn argument, so only check the // xit(), like it(), doesn't always have a fn argument, so only check the
@@ -2043,9 +2051,9 @@ getJasmineRequireObj().Env = function(j$) {
if (arguments.length > 1 && typeof fn !== 'undefined') { if (arguments.length > 1 && typeof fn !== 'undefined') {
ensureIsFunctionOrAsync(fn, 'xit'); ensureIsFunctionOrAsync(fn, 'xit');
} }
var spec = this.it.apply(this, arguments); var spec = this.it_.apply(this, arguments);
spec.pend('Temporarily disabled with xit'); spec.pend('Temporarily disabled with xit');
return spec; return spec.metadata;
}; };
this.fit = function(description, fn, timeout) { this.fit = function(description, fn, timeout) {
@@ -2055,7 +2063,7 @@ getJasmineRequireObj().Env = function(j$) {
currentDeclarationSuite.addChild(spec); currentDeclarationSuite.addChild(spec);
focusedRunnables.push(spec.id); focusedRunnables.push(spec.id);
unfocusAncestor(); unfocusAncestor();
return spec; return spec.metadata;
}; };
/** /**
@@ -9045,12 +9053,6 @@ getJasmineRequireObj().StackTrace = function(j$) {
getJasmineRequireObj().Suite = function(j$) { getJasmineRequireObj().Suite = function(j$) {
function Suite(attrs) { function Suite(attrs) {
this.env = attrs.env; this.env = attrs.env;
/**
* The unique ID of this suite.
* @name Suite#id
* @readonly
* @type {string}
*/
this.id = attrs.id; this.id = attrs.id;
this.parentSuite = attrs.parentSuite; this.parentSuite = attrs.parentSuite;
this.description = attrs.description; this.description = attrs.description;
@@ -9235,49 +9237,68 @@ getJasmineRequireObj().Suite = function(j$) {
); );
}; };
Suite.prototype.buildMetadata = function(parentMetadata) { Object.defineProperty(Suite.prototype, 'metadata', {
get: function() {
if (!this.metadata_) {
this.metadata_ = new SuiteMetadata(this);
}
return this.metadata_;
}
});
/**
* @interface Suite
* @see Env#topSuite
*/
function SuiteMetadata(suite) {
this.suite_ = suite;
/** /**
* @interface Suite * The unique ID of this suite.
* @see Env#topSuite * @name Suite#id
* @readonly
* @type {string}
*/ */
var result = { this.id = suite.id;
/**
* The parent of this suite, or null if this is the top suite.
* @name Suite#parentSuite
* @readonly
* @type {Suite}
*/
parentSuite: parentMetadata,
/**
* The description passed to the {@link describe} that created this suite.
* @name Suite#description
* @readonly
* @type {string}
*/
description: this.description,
/**
* The full description including all ancestors of this suite.
* @name Suite#getFullName
* @function
* @returns {string}
*/
getFullName: this.getFullName.bind(this)
};
/** /**
* The suite's children. * The parent of this suite, or null if this is the top suite.
* @name Suite#children * @name Suite#parentSuite
* @type {Array.<(Spec|Suite)>} * @readonly
* @type {Suite}
*/ */
result.children = this.children.map(function(child) { this.parentSuite = suite.parentSuite ? suite.parentSuite.metadata : null;
return child.buildMetadata(result);
});
return result; /**
* The description passed to the {@link describe} that created this suite.
* @name Suite#description
* @readonly
* @type {string}
*/
this.description = suite.description;
}
/**
* The full description including all ancestors of this suite.
* @name Suite#getFullName
* @function
* @returns {string}
*/
SuiteMetadata.prototype.getFullName = function() {
return this.suite_.getFullName();
}; };
/**
* The suite's children.
* @name Suite#children
* @type {Array.<(Spec|Suite)>}
*/
Object.defineProperty(SuiteMetadata.prototype, 'children', {
get: function() {
return this.suite_.children.map(child => child.metadata);
}
});
function isFailure(args) { function isFailure(args) {
return !args[0]; return !args[0];
} }
@@ -9285,11 +9306,6 @@ getJasmineRequireObj().Suite = function(j$) {
return Suite; return Suite;
}; };
if (typeof window == void 0 && typeof exports == 'object') {
/* globals exports */
exports.Suite = jasmineRequire.Suite;
}
getJasmineRequireObj().Timer = function() { getJasmineRequireObj().Timer = function() {
var defaultNow = (function(Date) { var defaultNow = (function(Date) {
return function() { return function() {
+74 -3
View File
@@ -90,7 +90,7 @@ describe('Env', function() {
it('can configure specs to throw errors on expectation failures', function() { it('can configure specs to throw errors on expectation failures', function() {
env.configure({ oneFailurePerSpec: true }); env.configure({ oneFailurePerSpec: true });
spyOn(jasmineUnderTest, 'Spec'); spyOn(jasmineUnderTest, 'Spec').and.callThrough();
env.it('foo', function() {}); env.it('foo', function() {});
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith( expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(
jasmine.objectContaining({ jasmine.objectContaining({
@@ -162,7 +162,7 @@ describe('Env', function() {
}); });
it('defaults to multiple failures for specs', function() { it('defaults to multiple failures for specs', function() {
spyOn(jasmineUnderTest, 'Spec'); spyOn(jasmineUnderTest, 'Spec').and.callThrough();
env.it('bar', function() {}); env.it('bar', function() {});
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith( expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(
jasmine.objectContaining({ jasmine.objectContaining({
@@ -181,7 +181,40 @@ describe('Env', function() {
); );
}); });
function behavesLikeDescribe(methodName) {
it('returns a suite metadata object', function() {
let innerSuite;
let spec;
const suite = env.describe('outer suite', function() {
innerSuite = env.describe('inner suite', function() {
spec = env.it('a spec');
});
});
expect(suite.parentSuite).toEqual(
jasmine.objectContaining({
description: 'Jasmine__TopLevel__Suite'
})
);
expect(suite.parentSuite.pend).toBeUndefined();
expect(suite.pend).toBeUndefined();
expect(suite.description).toEqual('outer suite');
expect(suite.getFullName()).toEqual('outer suite');
expect(suite.id).toBeInstanceOf(String);
expect(suite.id).not.toEqual('');
expect(suite.children.length).toEqual(1);
expect(suite.children[0]).toBe(innerSuite);
expect(innerSuite.children.length).toEqual(1);
expect(innerSuite.children[0]).toBe(spec);
expect(innerSuite.getFullName()).toEqual('outer suite inner suite');
expect(innerSuite.parentSuite).toBe(suite);
expect(spec.getFullName()).toEqual('outer suite inner suite a spec');
});
}
describe('#describe', function() { describe('#describe', function() {
behavesLikeDescribe('describe');
it('throws an error when given arguments', function() { it('throws an error when given arguments', function() {
expect(function() { expect(function() {
env.describe('done method', function(done) {}); env.describe('done method', function(done) {});
@@ -232,7 +265,41 @@ describe('Env', function() {
}); });
}); });
describe('#fdescribe', function() {
behavesLikeDescribe('fdescribe');
});
describe('xdescribe', function() {
behavesLikeDescribe('xdescribe');
});
function behavesLikeIt(methodName) {
it('returns a spec metadata object', function() {
let spec;
env.describe('a suite', function() {
spec = env[methodName]('a spec', function() {});
});
expect(spec.description)
.withContext('description')
.toEqual('a spec');
expect(spec.getFullName())
.withContext('getFullName')
.toEqual('a suite a spec');
expect(spec.id)
.withContext('id')
.toBeInstanceOf(String);
expect(spec.id)
.withContext('id')
.not.toEqual('');
expect(spec.pend).toBeFalsy();
});
}
describe('#it', function() { describe('#it', function() {
behavesLikeIt('it');
it('throws an error when it receives a non-fn argument', function() { it('throws an error when it receives a non-fn argument', function() {
expect(function() { expect(function() {
env.it('undefined arg', null); env.it('undefined arg', null);
@@ -255,9 +322,11 @@ describe('Env', function() {
}); });
describe('#xit', function() { describe('#xit', function() {
behavesLikeIt('xit');
it('calls spec.pend with "Temporarily disabled with xit"', function() { it('calls spec.pend with "Temporarily disabled with xit"', function() {
var pendSpy = jasmine.createSpy(); var pendSpy = jasmine.createSpy();
spyOn(env, 'it').and.returnValue({ spyOn(env, 'it_').and.returnValue({
pend: pendSpy pend: pendSpy
}); });
env.xit('foo', function() {}); env.xit('foo', function() {});
@@ -286,6 +355,8 @@ describe('Env', function() {
}); });
describe('#fit', function() { describe('#fit', function() {
behavesLikeIt('fit');
it('throws an error when it receives a non-fn argument', function() { it('throws an error when it receives a non-fn argument', function() {
expect(function() { expect(function() {
env.fit('undefined arg', undefined); env.fit('undefined arg', undefined);
+13 -8
View File
@@ -549,7 +549,7 @@ getJasmineRequireObj().Env = function(j$) {
* @return {Suite} the root suite * @return {Suite} the root suite
*/ */
this.topSuite = function() { this.topSuite = function() {
return topSuite.buildMetadata(null); return topSuite.metadata;
}; };
/** /**
@@ -932,7 +932,7 @@ getJasmineRequireObj().Env = function(j$) {
if (suite.parentSuite && !suite.children.length) { if (suite.parentSuite && !suite.children.length) {
throw new Error('describe with no children (describe() or it())'); throw new Error('describe with no children (describe() or it())');
} }
return suite; return suite.metadata;
}; };
this.xdescribe = function(description, specDefinitions) { this.xdescribe = function(description, specDefinitions) {
@@ -941,7 +941,7 @@ getJasmineRequireObj().Env = function(j$) {
var suite = suiteFactory(description); var suite = suiteFactory(description);
suite.pend(); suite.pend();
addSpecsToSuite(suite, specDefinitions); addSpecsToSuite(suite, specDefinitions);
return suite; return suite.metadata;
}; };
var focusedRunnables = []; var focusedRunnables = [];
@@ -956,7 +956,7 @@ getJasmineRequireObj().Env = function(j$) {
unfocusAncestor(); unfocusAncestor();
addSpecsToSuite(suite, specDefinitions); addSpecsToSuite(suite, specDefinitions);
return suite; return suite.metadata;
}; };
function addSpecsToSuite(suite, specDefinitions) { function addSpecsToSuite(suite, specDefinitions) {
@@ -1046,7 +1046,7 @@ getJasmineRequireObj().Env = function(j$) {
} }
}; };
this.it = function(description, fn, timeout) { this.it_ = function(description, fn, timeout) {
ensureIsNotNested('it'); ensureIsNotNested('it');
// it() sometimes doesn't have a fn argument, so only check the type if // it() sometimes doesn't have a fn argument, so only check the type if
// it's given. // it's given.
@@ -1062,6 +1062,11 @@ getJasmineRequireObj().Env = function(j$) {
return spec; return spec;
}; };
this.it = function(description, fn, timeout) {
const spec = this.it_(description, fn, timeout);
return spec.metadata;
};
this.xit = function(description, fn, timeout) { this.xit = function(description, fn, timeout) {
ensureIsNotNested('xit'); ensureIsNotNested('xit');
// xit(), like it(), doesn't always have a fn argument, so only check the // xit(), like it(), doesn't always have a fn argument, so only check the
@@ -1069,9 +1074,9 @@ getJasmineRequireObj().Env = function(j$) {
if (arguments.length > 1 && typeof fn !== 'undefined') { if (arguments.length > 1 && typeof fn !== 'undefined') {
ensureIsFunctionOrAsync(fn, 'xit'); ensureIsFunctionOrAsync(fn, 'xit');
} }
var spec = this.it.apply(this, arguments); var spec = this.it_.apply(this, arguments);
spec.pend('Temporarily disabled with xit'); spec.pend('Temporarily disabled with xit');
return spec; return spec.metadata;
}; };
this.fit = function(description, fn, timeout) { this.fit = function(description, fn, timeout) {
@@ -1081,7 +1086,7 @@ getJasmineRequireObj().Env = function(j$) {
currentDeclarationSuite.addChild(spec); currentDeclarationSuite.addChild(spec);
focusedRunnables.push(spec.id); focusedRunnables.push(spec.id);
unfocusAncestor(); unfocusAncestor();
return spec; return spec.metadata;
}; };
/** /**
+32 -29
View File
@@ -3,12 +3,6 @@ getJasmineRequireObj().Spec = function(j$) {
this.expectationFactory = attrs.expectationFactory; this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory; this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
/**
* The unique ID of this spec.
* @name Spec#id
* @readonly
* @type {string}
*/
this.id = attrs.id; this.id = attrs.id;
this.description = attrs.description || ''; this.description = attrs.description || '';
this.queueableFn = attrs.queueableFn; this.queueableFn = attrs.queueableFn;
@@ -238,30 +232,39 @@ getJasmineRequireObj().Spec = function(j$) {
* @interface Spec * @interface Spec
* @see Configuration#specFilter * @see Configuration#specFilter
*/ */
Spec.prototype.buildMetadata = function() { Object.defineProperty(Spec.prototype, 'metadata', {
return { get: function() {
/** if (!this.metadata_) {
* The description passed to the {@link it} that created this spec. this.metadata_ = {
* @name Spec#description /**
* @readonly * The unique ID of this spec.
* @type {string} * @name Spec#id
*/ * @readonly
description: this.description, * @type {string}
*/
id: this.id,
/** /**
* The full description including all ancestors of this spec. * The description passed to the {@link it} that created this spec.
* @name Spec#getFullName * @name Spec#description
* @function * @readonly
* @returns {string} * @type {string}
*/ */
getFullName: this.getFullName.bind(this) description: this.description,
};
}; /**
* The full description including all ancestors of this spec.
* @name Spec#getFullName
* @function
* @returns {string}
*/
getFullName: this.getFullName.bind(this)
};
}
return this.metadata_;
}
});
return Spec; return Spec;
}; };
if (typeof window == void 0 && typeof exports == 'object') {
/* globals exports */
exports.Spec = jasmineRequire.Spec;
}
+54 -46
View File
@@ -1,12 +1,6 @@
getJasmineRequireObj().Suite = function(j$) { getJasmineRequireObj().Suite = function(j$) {
function Suite(attrs) { function Suite(attrs) {
this.env = attrs.env; this.env = attrs.env;
/**
* The unique ID of this suite.
* @name Suite#id
* @readonly
* @type {string}
*/
this.id = attrs.id; this.id = attrs.id;
this.parentSuite = attrs.parentSuite; this.parentSuite = attrs.parentSuite;
this.description = attrs.description; this.description = attrs.description;
@@ -191,57 +185,71 @@ getJasmineRequireObj().Suite = function(j$) {
); );
}; };
Suite.prototype.buildMetadata = function(parentMetadata) { Object.defineProperty(Suite.prototype, 'metadata', {
get: function() {
if (!this.metadata_) {
this.metadata_ = new SuiteMetadata(this);
}
return this.metadata_;
}
});
/**
* @interface Suite
* @see Env#topSuite
*/
function SuiteMetadata(suite) {
this.suite_ = suite;
/** /**
* @interface Suite * The unique ID of this suite.
* @see Env#topSuite * @name Suite#id
* @readonly
* @type {string}
*/ */
var result = { this.id = suite.id;
/**
* The parent of this suite, or null if this is the top suite.
* @name Suite#parentSuite
* @readonly
* @type {Suite}
*/
parentSuite: parentMetadata,
/**
* The description passed to the {@link describe} that created this suite.
* @name Suite#description
* @readonly
* @type {string}
*/
description: this.description,
/**
* The full description including all ancestors of this suite.
* @name Suite#getFullName
* @function
* @returns {string}
*/
getFullName: this.getFullName.bind(this)
};
/** /**
* The suite's children. * The parent of this suite, or null if this is the top suite.
* @name Suite#children * @name Suite#parentSuite
* @type {Array.<(Spec|Suite)>} * @readonly
* @type {Suite}
*/ */
result.children = this.children.map(function(child) { this.parentSuite = suite.parentSuite ? suite.parentSuite.metadata : null;
return child.buildMetadata(result);
});
return result; /**
* The description passed to the {@link describe} that created this suite.
* @name Suite#description
* @readonly
* @type {string}
*/
this.description = suite.description;
}
/**
* The full description including all ancestors of this suite.
* @name Suite#getFullName
* @function
* @returns {string}
*/
SuiteMetadata.prototype.getFullName = function() {
return this.suite_.getFullName();
}; };
/**
* The suite's children.
* @name Suite#children
* @type {Array.<(Spec|Suite)>}
*/
Object.defineProperty(SuiteMetadata.prototype, 'children', {
get: function() {
return this.suite_.children.map(child => child.metadata);
}
});
function isFailure(args) { function isFailure(args) {
return !args[0]; return !args[0];
} }
return Suite; return Suite;
}; };
if (typeof window == void 0 && typeof exports == 'object') {
/* globals exports */
exports.Suite = jasmineRequire.Suite;
}