Deprecate access to non-public Suite and Spec members via Env#topSuite
The deprecation warning relies on Proxy, and won't work in environments that don't have it. Among Jasmine's supported environments, that's Safari 9, Safari 8, and all versions of IE.
This commit is contained in:
@@ -67,6 +67,8 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
|
||||
j$.Deprecator = jRequire.Deprecator(j$);
|
||||
j$.Env = jRequire.Env(j$);
|
||||
j$.deprecatingThisProxy = jRequire.deprecatingThisProxy(j$);
|
||||
j$.deprecatingSuiteProxy = jRequire.deprecatingSuiteProxy(j$);
|
||||
j$.deprecatingSpecProxy = jRequire.deprecatingSpecProxy(j$);
|
||||
j$.StackTrace = jRequire.StackTrace(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||
j$.ExpectationFilterChain = jRequire.ExpectationFilterChain();
|
||||
@@ -1738,7 +1740,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @return {Suite} the root suite
|
||||
*/
|
||||
this.topSuite = function() {
|
||||
return topSuite;
|
||||
return j$.deprecatingSuiteProxy(topSuite, null, this);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3693,6 +3695,176 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
|
||||
return DelayedFunctionScheduler;
|
||||
};
|
||||
|
||||
/* eslint-disable compat/compat */
|
||||
// TODO: Remove this in the next major release.
|
||||
getJasmineRequireObj().deprecatingSpecProxy = function(j$) {
|
||||
function isMember(target, prop) {
|
||||
return (
|
||||
Object.keys(target).indexOf(prop) !== -1 ||
|
||||
Object.keys(j$.Spec.prototype).indexOf(prop) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
function isAllowedMember(prop) {
|
||||
return prop === 'description' || prop === 'getFullName';
|
||||
}
|
||||
|
||||
function msg(member) {
|
||||
var memberName = member.toString().replace(/^Symbol\((.+)\)$/, '$1');
|
||||
return (
|
||||
'Access to private Spec members (in this case `' +
|
||||
memberName +
|
||||
'`) via Env#topSuite is not supported and will break in ' +
|
||||
'a future release. See <https://jasmine.github.io/api/edge/Spec.html> ' +
|
||||
'for correct usage.'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
new Proxy({}, {});
|
||||
} catch (e) {
|
||||
// Environment does not support Poxy.
|
||||
return function(spec) {
|
||||
return spec;
|
||||
};
|
||||
}
|
||||
|
||||
function DeprecatingSpecProxyHandler(env) {
|
||||
this._env = env;
|
||||
}
|
||||
|
||||
DeprecatingSpecProxyHandler.prototype.get = function(target, prop, receiver) {
|
||||
this._maybeDeprecate(target, prop);
|
||||
|
||||
if (prop === 'getFullName') {
|
||||
// getFullName calls a private method. Re-bind 'this' to avoid a bogus
|
||||
// deprecation warning.
|
||||
return target.getFullName.bind(target);
|
||||
} else {
|
||||
return target[prop];
|
||||
}
|
||||
};
|
||||
|
||||
DeprecatingSpecProxyHandler.prototype.set = function(target, prop, value) {
|
||||
this._maybeDeprecate(target, prop);
|
||||
return (target[prop] = value);
|
||||
};
|
||||
|
||||
DeprecatingSpecProxyHandler.prototype._maybeDeprecate = function(
|
||||
target,
|
||||
prop
|
||||
) {
|
||||
if (isMember(target, prop) && !isAllowedMember(prop)) {
|
||||
this._env.deprecated(msg(prop));
|
||||
}
|
||||
};
|
||||
|
||||
function deprecatingSpecProxy(spec, env) {
|
||||
return new Proxy(spec, new DeprecatingSpecProxyHandler(env));
|
||||
}
|
||||
|
||||
return deprecatingSpecProxy;
|
||||
};
|
||||
|
||||
/* eslint-disable compat/compat */
|
||||
// TODO: Remove this in the next major release.
|
||||
getJasmineRequireObj().deprecatingSuiteProxy = function(j$) {
|
||||
var allowedMembers = [
|
||||
'children',
|
||||
'description',
|
||||
'parentSuite',
|
||||
'getFullName'
|
||||
];
|
||||
|
||||
function isMember(target, prop) {
|
||||
return (
|
||||
Object.keys(target).indexOf(prop) !== -1 ||
|
||||
Object.keys(j$.Suite.prototype).indexOf(prop) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
function isAllowedMember(prop) {
|
||||
return allowedMembers.indexOf(prop) !== -1;
|
||||
}
|
||||
|
||||
function msg(member) {
|
||||
var memberName = member.toString().replace(/^Symbol\((.+)\)$/, '$1');
|
||||
return (
|
||||
'Access to private Suite members (in this case `' +
|
||||
memberName +
|
||||
'`) via Env#topSuite is not supported and will break in ' +
|
||||
'a future release. See <https://jasmine.github.io/api/edge/Suite.html> ' +
|
||||
'for correct usage.'
|
||||
);
|
||||
}
|
||||
try {
|
||||
new Proxy({}, {});
|
||||
} catch (e) {
|
||||
// Environment does not support Poxy.
|
||||
return function(suite) {
|
||||
return suite;
|
||||
};
|
||||
}
|
||||
|
||||
function DeprecatingSuiteProxyHandler(parentSuite, env) {
|
||||
this._parentSuite = parentSuite;
|
||||
this._env = env;
|
||||
}
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype.get = function(
|
||||
target,
|
||||
prop,
|
||||
receiver
|
||||
) {
|
||||
if (prop === 'children') {
|
||||
if (!this._children) {
|
||||
this._children = target.children.map(
|
||||
this._proxyForChild.bind(this, receiver)
|
||||
);
|
||||
}
|
||||
|
||||
return this._children;
|
||||
} else if (prop === 'parentSuite') {
|
||||
return this._parentSuite;
|
||||
} else {
|
||||
this._maybeDeprecate(target, prop);
|
||||
return target[prop];
|
||||
}
|
||||
};
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype.set = function(target, prop, value) {
|
||||
debugger;
|
||||
this._maybeDeprecate(target, prop);
|
||||
return (target[prop] = value);
|
||||
};
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype._maybeDeprecate = function(
|
||||
target,
|
||||
prop
|
||||
) {
|
||||
if (isMember(target, prop) && !isAllowedMember(prop)) {
|
||||
this._env.deprecated(msg(prop));
|
||||
}
|
||||
};
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype._proxyForChild = function(
|
||||
ownProxy,
|
||||
child
|
||||
) {
|
||||
if (child.children) {
|
||||
return deprecatingSuiteProxy(child, ownProxy, this._env);
|
||||
} else {
|
||||
return j$.deprecatingSpecProxy(child, this._env);
|
||||
}
|
||||
};
|
||||
|
||||
function deprecatingSuiteProxy(suite, parentSuite, env) {
|
||||
return new Proxy(suite, new DeprecatingSuiteProxyHandler(parentSuite, env));
|
||||
}
|
||||
|
||||
return deprecatingSuiteProxy;
|
||||
};
|
||||
|
||||
/* eslint-disable compat/compat */
|
||||
// TODO: Remove this in the next major release.
|
||||
getJasmineRequireObj().deprecatingThisProxy = function(j$) {
|
||||
|
||||
@@ -26,9 +26,141 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
describe('#topSuite', function() {
|
||||
it('returns the Jasmine top suite for users to traverse the spec tree', function() {
|
||||
var suite = env.topSuite();
|
||||
it('returns an object that describes the tree of suites and specs', function() {
|
||||
var suite;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.it('a top level spec');
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec');
|
||||
env.describe('a nested suite', function() {
|
||||
env.it('a nested spec');
|
||||
});
|
||||
});
|
||||
|
||||
suite = env.topSuite();
|
||||
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
|
||||
expect(suite.getFullName()).toEqual('');
|
||||
expect(suite.children.length).toEqual(2);
|
||||
|
||||
expect(suite.children[0].description).toEqual('a top level spec');
|
||||
expect(suite.children[0].getFullName()).toEqual('a top level spec');
|
||||
expect(suite.children[0].children).toBeFalsy();
|
||||
|
||||
expect(suite.children[1].description).toEqual('a suite');
|
||||
expect(suite.children[1].getFullName()).toEqual('a suite');
|
||||
expect(suite.children[1].parentSuite).toBe(suite);
|
||||
expect(suite.children[1].children.length).toEqual(2);
|
||||
|
||||
expect(suite.children[1].children[0].description).toEqual('a spec');
|
||||
expect(suite.children[1].children[0].getFullName()).toEqual(
|
||||
'a suite a spec'
|
||||
);
|
||||
expect(suite.children[1].children[0].children).toBeFalsy();
|
||||
|
||||
expect(suite.children[1].children[1].description).toEqual(
|
||||
'a nested suite'
|
||||
);
|
||||
expect(suite.children[1].children[1].getFullName()).toEqual(
|
||||
'a suite a nested suite'
|
||||
);
|
||||
expect(suite.children[1].children[1].parentSuite).toBe(suite.children[1]);
|
||||
expect(suite.children[1].children[1].children.length).toEqual(1);
|
||||
|
||||
expect(suite.children[1].children[1].children[0].description).toEqual(
|
||||
'a nested spec'
|
||||
);
|
||||
expect(suite.children[1].children[1].children[0].getFullName()).toEqual(
|
||||
'a suite a nested suite a nested spec'
|
||||
);
|
||||
expect(suite.children[1].children[1].children[0].children).toBeFalsy();
|
||||
});
|
||||
|
||||
it('does not deprecate access to public Suite and Spec members', function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
var suite;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.it('a top level spec');
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec');
|
||||
});
|
||||
|
||||
suite = env.topSuite();
|
||||
suite.description;
|
||||
suite.getFullName();
|
||||
suite.children;
|
||||
suite.parentSuite;
|
||||
suite.children[0].description;
|
||||
suite.children[0].getFullName();
|
||||
suite.children[0].children;
|
||||
|
||||
suite.children[1].description;
|
||||
suite.children[1].getFullName();
|
||||
suite.children[1].parentSuite;
|
||||
suite.children[1].children;
|
||||
|
||||
expect(env.deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('deprecates access to internal Suite and Spec members', function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
var topSuite, expectationFactory, spec;
|
||||
|
||||
env.it('a top level spec');
|
||||
spyOn(env, 'deprecated');
|
||||
topSuite = env.topSuite();
|
||||
|
||||
topSuite.expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `expectationFactory`) via Env#topSuite is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
topSuite.expectationFactory = expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `expectationFactory`) via Env#topSuite is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
|
||||
topSuite.status();
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `status`) via Env#topSuite is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
|
||||
spec = topSuite.children[0];
|
||||
spec.pend();
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Spec ' +
|
||||
'members (in this case `pend`) via Env#topSuite ' +
|
||||
'is not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
|
||||
expectationFactory = spec.expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Spec ' +
|
||||
'members (in this case `expectationFactory`) via Env#topSuite ' +
|
||||
'is not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
spec.expectationFactory = expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Spec ' +
|
||||
'members (in this case `expectationFactory`) via Env#topSuite ' +
|
||||
'is not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -734,7 +734,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @return {Suite} the root suite
|
||||
*/
|
||||
this.topSuite = function() {
|
||||
return topSuite;
|
||||
return j$.deprecatingSuiteProxy(topSuite, null, this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
70
src/core/deprecatingSpecProxy.js
Normal file
70
src/core/deprecatingSpecProxy.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/* eslint-disable compat/compat */
|
||||
// TODO: Remove this in the next major release.
|
||||
getJasmineRequireObj().deprecatingSpecProxy = function(j$) {
|
||||
function isMember(target, prop) {
|
||||
return (
|
||||
Object.keys(target).indexOf(prop) !== -1 ||
|
||||
Object.keys(j$.Spec.prototype).indexOf(prop) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
function isAllowedMember(prop) {
|
||||
return prop === 'description' || prop === 'getFullName';
|
||||
}
|
||||
|
||||
function msg(member) {
|
||||
var memberName = member.toString().replace(/^Symbol\((.+)\)$/, '$1');
|
||||
return (
|
||||
'Access to private Spec members (in this case `' +
|
||||
memberName +
|
||||
'`) via Env#topSuite is not supported and will break in ' +
|
||||
'a future release. See <https://jasmine.github.io/api/edge/Spec.html> ' +
|
||||
'for correct usage.'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
new Proxy({}, {});
|
||||
} catch (e) {
|
||||
// Environment does not support Poxy.
|
||||
return function(spec) {
|
||||
return spec;
|
||||
};
|
||||
}
|
||||
|
||||
function DeprecatingSpecProxyHandler(env) {
|
||||
this._env = env;
|
||||
}
|
||||
|
||||
DeprecatingSpecProxyHandler.prototype.get = function(target, prop, receiver) {
|
||||
this._maybeDeprecate(target, prop);
|
||||
|
||||
if (prop === 'getFullName') {
|
||||
// getFullName calls a private method. Re-bind 'this' to avoid a bogus
|
||||
// deprecation warning.
|
||||
return target.getFullName.bind(target);
|
||||
} else {
|
||||
return target[prop];
|
||||
}
|
||||
};
|
||||
|
||||
DeprecatingSpecProxyHandler.prototype.set = function(target, prop, value) {
|
||||
this._maybeDeprecate(target, prop);
|
||||
return (target[prop] = value);
|
||||
};
|
||||
|
||||
DeprecatingSpecProxyHandler.prototype._maybeDeprecate = function(
|
||||
target,
|
||||
prop
|
||||
) {
|
||||
if (isMember(target, prop) && !isAllowedMember(prop)) {
|
||||
this._env.deprecated(msg(prop));
|
||||
}
|
||||
};
|
||||
|
||||
function deprecatingSpecProxy(spec, env) {
|
||||
return new Proxy(spec, new DeprecatingSpecProxyHandler(env));
|
||||
}
|
||||
|
||||
return deprecatingSpecProxy;
|
||||
};
|
||||
98
src/core/deprecatingSuiteProxy.js
Normal file
98
src/core/deprecatingSuiteProxy.js
Normal file
@@ -0,0 +1,98 @@
|
||||
/* eslint-disable compat/compat */
|
||||
// TODO: Remove this in the next major release.
|
||||
getJasmineRequireObj().deprecatingSuiteProxy = function(j$) {
|
||||
var allowedMembers = [
|
||||
'children',
|
||||
'description',
|
||||
'parentSuite',
|
||||
'getFullName'
|
||||
];
|
||||
|
||||
function isMember(target, prop) {
|
||||
return (
|
||||
Object.keys(target).indexOf(prop) !== -1 ||
|
||||
Object.keys(j$.Suite.prototype).indexOf(prop) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
function isAllowedMember(prop) {
|
||||
return allowedMembers.indexOf(prop) !== -1;
|
||||
}
|
||||
|
||||
function msg(member) {
|
||||
var memberName = member.toString().replace(/^Symbol\((.+)\)$/, '$1');
|
||||
return (
|
||||
'Access to private Suite members (in this case `' +
|
||||
memberName +
|
||||
'`) via Env#topSuite is not supported and will break in ' +
|
||||
'a future release. See <https://jasmine.github.io/api/edge/Suite.html> ' +
|
||||
'for correct usage.'
|
||||
);
|
||||
}
|
||||
try {
|
||||
new Proxy({}, {});
|
||||
} catch (e) {
|
||||
// Environment does not support Poxy.
|
||||
return function(suite) {
|
||||
return suite;
|
||||
};
|
||||
}
|
||||
|
||||
function DeprecatingSuiteProxyHandler(parentSuite, env) {
|
||||
this._parentSuite = parentSuite;
|
||||
this._env = env;
|
||||
}
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype.get = function(
|
||||
target,
|
||||
prop,
|
||||
receiver
|
||||
) {
|
||||
if (prop === 'children') {
|
||||
if (!this._children) {
|
||||
this._children = target.children.map(
|
||||
this._proxyForChild.bind(this, receiver)
|
||||
);
|
||||
}
|
||||
|
||||
return this._children;
|
||||
} else if (prop === 'parentSuite') {
|
||||
return this._parentSuite;
|
||||
} else {
|
||||
this._maybeDeprecate(target, prop);
|
||||
return target[prop];
|
||||
}
|
||||
};
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype.set = function(target, prop, value) {
|
||||
debugger;
|
||||
this._maybeDeprecate(target, prop);
|
||||
return (target[prop] = value);
|
||||
};
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype._maybeDeprecate = function(
|
||||
target,
|
||||
prop
|
||||
) {
|
||||
if (isMember(target, prop) && !isAllowedMember(prop)) {
|
||||
this._env.deprecated(msg(prop));
|
||||
}
|
||||
};
|
||||
|
||||
DeprecatingSuiteProxyHandler.prototype._proxyForChild = function(
|
||||
ownProxy,
|
||||
child
|
||||
) {
|
||||
if (child.children) {
|
||||
return deprecatingSuiteProxy(child, ownProxy, this._env);
|
||||
} else {
|
||||
return j$.deprecatingSpecProxy(child, this._env);
|
||||
}
|
||||
};
|
||||
|
||||
function deprecatingSuiteProxy(suite, parentSuite, env) {
|
||||
return new Proxy(suite, new DeprecatingSuiteProxyHandler(parentSuite, env));
|
||||
}
|
||||
|
||||
return deprecatingSuiteProxy;
|
||||
};
|
||||
@@ -45,6 +45,8 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
|
||||
j$.Deprecator = jRequire.Deprecator(j$);
|
||||
j$.Env = jRequire.Env(j$);
|
||||
j$.deprecatingThisProxy = jRequire.deprecatingThisProxy(j$);
|
||||
j$.deprecatingSuiteProxy = jRequire.deprecatingSuiteProxy(j$);
|
||||
j$.deprecatingSpecProxy = jRequire.deprecatingSpecProxy(j$);
|
||||
j$.StackTrace = jRequire.StackTrace(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||
j$.ExpectationFilterChain = jRequire.ExpectationFilterChain();
|
||||
|
||||
Reference in New Issue
Block a user