Detect monkey patching and emit a deprecation warning.
This isn't comprehensive but it should be broad enough to ensure that most people who would be affected by blocking monkey patching see a warning. Covers the jasmine namespace as well as classes that are monkey patched by zone.js. Replacing globals (describe/it/etc) doesn't trigger a warning because they belong to the user and are expected to be replaced.
This commit is contained in:
@@ -1247,4 +1247,25 @@ describe('Clock (acceptance)', function() {
|
||||
|
||||
clock.tick(400);
|
||||
});
|
||||
|
||||
describe('Warning about monkey patching', function() {
|
||||
for (const name of ['tick', 'mockDate', 'install', 'uninstall']) {
|
||||
it(`warns if Clock#${name} is monkey patched`, function() {
|
||||
spyOn(console, 'error');
|
||||
const clock = new privateUnderTest.Clock({}, function() {}, {});
|
||||
const patch = {};
|
||||
clock[name] = patch;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringContaining('DEPRECATION: Monkey patching detected.')
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringContaining('ClockSpec.js')
|
||||
);
|
||||
expect(clock[name]).toBe(patch);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,8 +26,6 @@ describe('Env', function() {
|
||||
|
||||
describe('#topSuite', function() {
|
||||
it('returns an object that describes the tree of suites and specs', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.it('a top level spec');
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec');
|
||||
@@ -123,7 +121,6 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('ignores configuration properties that are present but undefined', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
const initialConfig = {
|
||||
random: true,
|
||||
seed: '123',
|
||||
@@ -763,7 +760,6 @@ describe('Env', function() {
|
||||
|
||||
it("does not expose the suite as 'this'", function() {
|
||||
let suiteThis;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
suiteThis = this;
|
||||
@@ -878,4 +874,37 @@ describe('Env', function() {
|
||||
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Warning about monkey patching', function() {
|
||||
const names = [
|
||||
'describe',
|
||||
'xdescribe',
|
||||
'fdescribe',
|
||||
'it',
|
||||
'xit',
|
||||
'fit',
|
||||
'beforeEach',
|
||||
'afterEach',
|
||||
'beforeAll',
|
||||
'afterAll'
|
||||
];
|
||||
|
||||
for (const name of names) {
|
||||
it(`warns if Env#${name} is monkey patched`, function() {
|
||||
spyOn(console, 'error');
|
||||
const patch = {};
|
||||
env[name] = patch;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringContaining('DEPRECATION: Monkey patching detected.')
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringContaining('EnvSpec.js')
|
||||
);
|
||||
expect(env[name]).toBe(patch);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -170,8 +170,15 @@ describe('base helpers', function() {
|
||||
});
|
||||
|
||||
describe('debugLog', function() {
|
||||
beforeEach(function() {
|
||||
privateUnderTest.currentEnv_ = jasmine.createSpyObj('env', ['debugLog']);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
privateUnderTest.currentEnv_ = null;
|
||||
});
|
||||
|
||||
it("forwards to the current env's debugLog function", function() {
|
||||
spyOn(jasmineUnderTest.getEnv(), 'debugLog');
|
||||
jasmineUnderTest.debugLog('a message');
|
||||
expect(jasmineUnderTest.getEnv().debugLog).toHaveBeenCalledWith(
|
||||
'a message'
|
||||
|
||||
@@ -13,7 +13,72 @@ describe('The jasmine namespace', function() {
|
||||
expect(setDifference(actualKeys, expectedKeys())).toEqual(new Set());
|
||||
});
|
||||
|
||||
function expectedKeys() {
|
||||
describe('Warning about monkey patching', function() {
|
||||
beforeEach(function() {
|
||||
spyOn(console, 'error');
|
||||
});
|
||||
|
||||
for (const key of expectedKeys(false)) {
|
||||
if (!key.startsWith('MAX_') && key !== 'private' && key !== 'getEnv') {
|
||||
describe(`jasmine.${key}`, function() {
|
||||
let orig;
|
||||
|
||||
beforeEach(function() {
|
||||
orig = jasmineUnderTest[key];
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmineUnderTest[key] = orig;
|
||||
});
|
||||
|
||||
it('warns if monkey patched', function() {
|
||||
const patch = {};
|
||||
jasmineUnderTest[key] = patch;
|
||||
|
||||
verifyDeprecation();
|
||||
expect(jasmineUnderTest[key]).toBe(patch);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// These specs rely on jasmineRequire being exposed. That only happens
|
||||
// in browsers.
|
||||
if (typeof document !== 'undefined') {
|
||||
const statics = ['addMatchers', 'clock', 'createSpyObj'];
|
||||
|
||||
for (const name of statics) {
|
||||
describe(`jasmine.${name}`, function() {
|
||||
let bootedCore, env, orig;
|
||||
|
||||
beforeEach(function() {
|
||||
bootedCore = jasmineRequire.core(jasmineRequire);
|
||||
env = bootedCore.getEnv();
|
||||
jasmineRequire.interface(bootedCore, env);
|
||||
orig = bootedCore[name];
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
bootedCore[name] = orig;
|
||||
env.cleanup_();
|
||||
});
|
||||
|
||||
it(`warns if jasmine.${name} is monkey patched`, function() {
|
||||
const patch = {};
|
||||
bootedCore[name] = patch;
|
||||
|
||||
verifyDeprecation();
|
||||
expect(bootedCore[name]).toBe(patch);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function expectedKeys(includeHtml) {
|
||||
if (includeHtml === undefined) {
|
||||
includeHtml = typeof window !== 'undefined';
|
||||
}
|
||||
// Does not include properties added by requireInterface(), since that isn't
|
||||
// called by defineJasmineUnderTest.js/nodeDefineJasmineUnderTest.js.
|
||||
const result = new Set([
|
||||
@@ -51,7 +116,7 @@ describe('The jasmine namespace', function() {
|
||||
'getGlobal'
|
||||
]);
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
if (includeHtml) {
|
||||
// jasmine-html.js
|
||||
result.add('HtmlReporter');
|
||||
result.add('HtmlReporterV2');
|
||||
@@ -76,4 +141,15 @@ describe('The jasmine namespace', function() {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function verifyDeprecation() {
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringContaining('DEPRECATION: Monkey patching detected.')
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringContaining('jasmineNamespaceSpec.js')
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
describe('HtmlReporter', function() {
|
||||
let env;
|
||||
let env, deprecator;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new privateUnderTest.Env();
|
||||
spyOn(env, 'deprecated');
|
||||
deprecator = jasmine.createSpyObj('deprecator', [
|
||||
'verboseDeprecations',
|
||||
'addDeprecationWarning'
|
||||
]);
|
||||
env = new privateUnderTest.Env({ deprecator });
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -21,8 +24,10 @@ describe('HtmlReporter', function() {
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'HtmlReporter and HtmlSpecFilter are deprecated. Use HtmlReporterV2 instead.'
|
||||
expect(deprecator.addDeprecationWarning).toHaveBeenCalledWith(
|
||||
jasmine.anything(),
|
||||
'HtmlReporter and HtmlSpecFilter are deprecated. Use HtmlReporterV2 instead.',
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,17 +1,29 @@
|
||||
describe('HtmlSpecFilter', function() {
|
||||
let env, deprecator;
|
||||
|
||||
beforeEach(function() {
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
deprecator = jasmine.createSpyObj('deprecator', [
|
||||
'verboseDeprecations',
|
||||
'addDeprecationWarning'
|
||||
]);
|
||||
env = new privateUnderTest.Env({ deprecator });
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
env.cleanup_();
|
||||
});
|
||||
|
||||
it('emits a deprecation warning', function() {
|
||||
new jasmineUnderTest.HtmlSpecFilter();
|
||||
expect(jasmineUnderTest.getEnv().deprecated).toHaveBeenCalledWith(
|
||||
'HtmlReporter and HtmlSpecFilter are deprecated. Use HtmlReporterV2 instead.'
|
||||
new jasmineUnderTest.HtmlSpecFilter({ env });
|
||||
expect(deprecator.addDeprecationWarning).toHaveBeenCalledWith(
|
||||
jasmine.anything(),
|
||||
'HtmlReporter and HtmlSpecFilter are deprecated. Use HtmlReporterV2 instead.',
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
it('should match when no string is provided', function() {
|
||||
const specFilter = new jasmineUnderTest.HtmlSpecFilter();
|
||||
const specFilter = new jasmineUnderTest.HtmlSpecFilter({ env });
|
||||
|
||||
expect(specFilter.matches('foo')).toBe(true);
|
||||
expect(specFilter.matches('*bar')).toBe(true);
|
||||
@@ -19,6 +31,7 @@ describe('HtmlSpecFilter', function() {
|
||||
|
||||
it('should only match the provided string', function() {
|
||||
const specFilter = new jasmineUnderTest.HtmlSpecFilter({
|
||||
env,
|
||||
filterString: function() {
|
||||
return 'foo';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user