Skip to content

Commit

Permalink
Add a "errorOnDeprecated" mode that errors when calling deprecated AP…
Browse files Browse the repository at this point in the history
…Is (#6339)

* Add a "errorOnDeprecated" mode that errors when accessing unsupported jasmine
features.

This lays the groundwork for adding other helpful errors for deprecated
features/APIs.

* Ignore error-on-deprecated in circus... for now

* Trim stacktrace

* Fix typos

* Remove deprecation error for DEFAULT_TIMEOUT_INTERVAL
  • Loading branch information
captbaritone authored and cpojer committed May 30, 2018
1 parent 9035b15 commit 9b3b583
Show file tree
Hide file tree
Showing 27 changed files with 543 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Features

* `[jest-watch]` create new package `jest-watch` to ease custom watch plugin development ([#6318](https://github.com/facebook/jest/pull/6318))
* Add a config/CLI option `errorOnDeprecated` which makes calling deprecated APIs throw hepful error messages.

### Fixes

Expand Down
2 changes: 2 additions & 0 deletions TestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {
detectLeaks: false,
detectOpenHandles: false,
enabledTestsMap: null,
errorOnDeprecated: false,
expand: false,
filter: null,
findRelatedTests: false,
Expand Down Expand Up @@ -75,6 +76,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = {
detectLeaks: false,
detectOpenHandles: false,
displayName: undefined,
errorOnDeprecated: false,
filter: null,
forceCoverageMatch: [],
globals: {},
Expand Down
4 changes: 4 additions & 0 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ Attempt to collect and print open handles preventing Jest from exiting cleanly.

The test environment used for all tests. This can point to any file or node module. Examples: `jsdom`, `node` or `path/to/my-environment.js`.

### `--errorOnDeprecated`

Make calling deprecated APIs throw helpful error messages. Useful for easing the upgrade process.

### `--expand`

Alias: `-e`. Use this flag to show full diffs and errors instead of a patch.
Expand Down
6 changes: 6 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,12 @@ Pretty foo: Object {

To make a dependency explicit instead of implicit, you can call [`expect.addSnapshotSerializer`](ExpectAPI.md#expectaddsnapshotserializerserializer) to add a module for an individual test file instead of adding its path to `snapshotSerializers` in Jest configuration.

### `errorOnDeprecated` [boolean]

Default: `false`

Make calling deprecated APIs throw helpful error messages. Useful for easing the upgrade process.

### `testEnvironment` [string]

Default: `"jsdom"`
Expand Down
226 changes: 226 additions & 0 deletions e2e/__tests__/__snapshots__/error-on-deprecated.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`fail.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/fail.test.js
✕ fail
● fail
Illegal usage of global \`fail\`, prefer throwing an error, or the \`done.fail\` callback.
11 | test('fail', () => {
12 | if (true) {
> 13 | fail('The truth hurts!');
| ^
14 | }
15 | });
16 |
at __tests__/fail.test.js:13:5
"
`;

exports[`jasmine.addMatchers.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.addMatchers.test.js
● Test suite failed to run
Illegal usage of \`jasmine.addMatchers\`, prefer \`expect.extends\`.
7 | 'use strict';
8 |
> 9 | jasmine.addMatchers({
| ^
10 | theSpanishInquisition: () => ({
11 | compare: (actual, expected) => ({
12 | message: 'Nobdy expects the Spanish Inquisition!',
at __tests__/jasmine.addMatchers.test.js:9:9
"
`;
exports[`jasmine.any.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.any.test.js
✕ jasmine.any
● jasmine.any
Illegal usage of \`jasmine.any\`, prefer \`expect.any\`.
8 |
9 | test('jasmine.any', () => {
> 10 | expect({name: 'Jessie'}).toEqual({name: jasmine.any(String)});
| ^
11 | });
12 |
at __tests__/jasmine.any.test.js:10:51
"
`;
exports[`jasmine.anything.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.anything.test.js
✕ jasmine.anything
● jasmine.anything
Illegal usage of \`jasmine.anything\`, prefer \`expect.anything\`.
8 |
9 | test('jasmine.anything', () => {
> 10 | expect({input: ['some', 'stuff']}).toEqual({input: jasmine.anything()});
| ^
11 | });
12 |
at __tests__/jasmine.anything.test.js:10:62
"
`;
exports[`jasmine.arrayContaining.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.arrayContaining.test.js
✕ jasmine.arrayContaining
● jasmine.arrayContaining
Illegal usage of \`jasmine.arrayContaining\`, prefer \`expect.arrayContaining\`.
8 |
9 | test('jasmine.arrayContaining', () => {
> 10 | expect(['some', 'stuff']).toEqual(jasmine.arrayContaining(['stuff']));
| ^
11 | });
12 |
at __tests__/jasmine.arrayContaining.test.js:10:45
"
`;
exports[`jasmine.createSpy.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.createSpy.test.js
✕ jasmine.createSpy
● jasmine.createSpy
Illegal usage of \`jasmine.createSpy\`, prefer \`jest.fn\`.
8 |
9 | test('jasmine.createSpy', () => {
> 10 | const mySpy = jasmine.createSpy();
| ^
11 | mySpy('hello?');
12 | expect(mySpy).toHaveBeenCalledWith('hello?');
13 | });
at __tests__/jasmine.createSpy.test.js:10:25
"
`;
exports[`jasmine.objectContaining.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.objectContaining.test.js
✕ jasmine.objectContaining
● jasmine.objectContaining
Illegal usage of \`jasmine.objectContaining\`, prefer \`expect.objectContaining\`.
9 | test('jasmine.objectContaining', () => {
10 | expect({input: 'trash', output: 'trash'}).toEqual(
> 11 | jasmine.objectContaining({output: 'trash'})
| ^
12 | );
13 | });
14 |
at __tests__/jasmine.objectContaining.test.js:11:13
"
`;
exports[`jasmine.stringMatching.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/jasmine.stringMatching.test.js
✕ jasmine.stringMatching
● jasmine.stringMatching
Illegal usage of \`jasmine.stringMatching\`, prefer \`expect.stringMatching\`.
8 |
9 | test('jasmine.stringMatching', () => {
> 10 | expect('Greetings Earthling!').toEqual(jasmine.stringMatching(/^Greetings/));
| ^
11 | });
12 |
at __tests__/jasmine.stringMatching.test.js:10:50
"
`;
exports[`pending.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/pending.test.js
✕ pending
● pending
Illegal usage of global \`pending\`, prefer explicitly skipping a test using \`test.skip\`
9 | test('pending', () => {
10 | if (true) {
> 11 | pending('This test is pending.');
| ^
12 | }
13 | expect(false).toBe(true);
14 | });
at __tests__/pending.test.js:11:5
"
`;
exports[`spyOn.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/spyOn.test.js
✕ spyOn
● spyOn
Illegal usage of global \`spyOn\`, prefer \`jest.spyOn\`.
15 |
16 | test('spyOn', () => {
> 17 | spyOn(subject, 'func').and.returnValue('bar');
| ^
18 | expect(subject.func()).toBe('bar');
19 | });
20 |
at __tests__/spyOn.test.js:17:3
"
`;
exports[`spyOnProperty.test.js errors in errorOnDeprecated mode 1`] = `
"FAIL __tests__/spyOnProperty.test.js
✕ spyOnProperty
● spyOnProperty
Illegal usage of global \`spyOnProperty\`, prefer \`jest.spyOn\`.
22 | };
23 |
> 24 | const spy = spyOnProperty(obj, 'method', 'get');
| ^
25 |
26 | obj.method();
27 |
at __tests__/spyOnProperty.test.js:24:15
"
`;
2 changes: 2 additions & 0 deletions e2e/__tests__/__snapshots__/show_config.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
],
\\"detectLeaks\\": false,
\\"detectOpenHandles\\": false,
\\"errorOnDeprecated\\": false,
\\"filter\\": null,
\\"forceCoverageMatch\\": [],
\\"globals\\": {},
Expand Down Expand Up @@ -81,6 +82,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
],
\\"detectLeaks\\": false,
\\"detectOpenHandles\\": false,
\\"errorOnDeprecated\\": false,
\\"expand\\": false,
\\"filter\\": null,
\\"globalSetup\\": null,
Expand Down
58 changes: 58 additions & 0 deletions e2e/__tests__/error-on-deprecated.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
'use strict';

const runJest = require('../runJest');
const {extractSummary} = require('../Utils');
const ConditionalTest = require('../../scripts/ConditionalTest');

ConditionalTest.skipSuiteOnJestCircus();

const testFiles = [
'fail.test.js',
'jasmine.addMatchers.test.js',
'jasmine.any.test.js',
'jasmine.anything.test.js',
'jasmine.arrayContaining.test.js',
'jasmine.createSpy.test.js',
'jasmine.objectContaining.test.js',
'jasmine.stringMatching.test.js',
'pending.test.js',
'spyOn.test.js',
'spyOnProperty.test.js',
];

const SHOULD_NOT_PASS_IN_JEST = new Set([
'fail.test.js',
'spyOnProperty.test.js',
]);

testFiles.forEach(testFile => {
test(`${testFile} errors in errorOnDeprecated mode`, () => {
const result = runJest('error-on-deprecated', [
testFile,
'--errorOnDeprecated',
]);
expect(result.status).toBe(1);
const {rest} = extractSummary(result.stderr);
expect(rest).toMatchSnapshot();
});
});

testFiles.forEach(testFile => {
const shouldPass = SHOULD_NOT_PASS_IN_JEST.has(testFile);

const expectation = `${testFile} ${shouldPass ? 'errors' : 'passes'}`;
const testName = `${expectation} when not in errorOnDeprecated mode`;

test(testName, () => {
const result = runJest('error-on-deprecated', [testFile]);
expect(result.status).toBe(shouldPass ? 1 : 0);
});
});
15 changes: 15 additions & 0 deletions e2e/error-on-deprecated/__tests__/fail.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';

/* globals fail */

test('fail', () => {
if (true) {
fail('The truth hurts!');
}
});
20 changes: 20 additions & 0 deletions e2e/error-on-deprecated/__tests__/jasmine.addMatchers.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';

jasmine.addMatchers({
theSpanishInquisition: () => ({
compare: (actual, expected) => ({
message: 'Nobdy expects the Spanish Inquisition!',
pass: false,
}),
}),
});

test('jasmine.addMatchers', () => {
expect('Anybody').not.theSpanishInquisition();
});
11 changes: 11 additions & 0 deletions e2e/error-on-deprecated/__tests__/jasmine.any.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';

test('jasmine.any', () => {
expect({name: 'Jessie'}).toEqual({name: jasmine.any(String)});
});

0 comments on commit 9b3b583

Please sign in to comment.