Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: check for common errors when using the wrong test environment #8245

Merged
merged 9 commits into from Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,8 @@

### Features

- `[jest-message-util]` Check for common errors when using the wrong test environment ([#8245](https://github.com/facebook/jest/pull/8245))

### Fixes

- `[jest-circus]` Fix type ellision of jest-runtime imports ([#9717](https://github.com/facebook/jest/pull/9717))
Expand Down
115 changes: 115 additions & 0 deletions e2e/__tests__/__snapshots__/wrongEnv.test.ts.snap
@@ -0,0 +1,115 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Wrong globals for environment print useful error for document 1`] = `
FAIL __tests__/node.js
✕ use document
○ skipped use window
○ skipped use navigator

● use document

The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/en/configuration#testenvironment-string.
Consider using the "jsdom" test environment.

ReferenceError: document is not defined

14 |
15 | test('use document', () => {
> 16 | const div = document.createElement('div');
| ^
17 |
18 | console.log(div);
19 |

at Object.document (__tests__/node.js:16:15)
`;

exports[`Wrong globals for environment print useful error for navigator 1`] = `
FAIL __tests__/node.js
✕ use navigator
○ skipped use document
○ skipped use window

● use navigator

The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/en/configuration#testenvironment-string.
Consider using the "jsdom" test environment.

ReferenceError: navigator is not defined

30 |
31 | test('use navigator', () => {
> 32 | const userAgent = navigator.userAgent;
| ^
33 |
34 | console.log(userAgent);
35 |

at Object.navigator (__tests__/node.js:32:21)
`;

exports[`Wrong globals for environment print useful error for unref 1`] = `
FAIL __tests__/jsdom.js
✕ use unref

● use unref

The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/en/configuration#testenvironment-string.
Consider using the "node" test environment.

TypeError: setTimeout(...).unref is not a function

11 |
12 | test('use unref', () => {
> 13 | setTimeout(() => {}, 0).unref();
| ^
14 |
15 | expect(1).toBe(1);
16 | });

at Object.unref (__tests__/jsdom.js:13:27)
`;

exports[`Wrong globals for environment print useful error for window 1`] = `
FAIL __tests__/node.js
✕ use window
○ skipped use document
○ skipped use navigator

● use window

The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/en/configuration#testenvironment-string.
Consider using the "jsdom" test environment.

ReferenceError: window is not defined

22 |
23 | test('use window', () => {
> 24 | const location = window.location;
| ^
25 |
26 | console.log(location);
27 |

at Object.window (__tests__/node.js:24:20)
`;

exports[`Wrong globals for environment print useful error when it explodes during evaluation 1`] = `
FAIL __tests__/beforeTest.js
● Test suite failed to run

The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/en/configuration#testenvironment-string.
Consider using the "jsdom" test environment.

ReferenceError: document is not defined

11 | /* eslint-env browser */
12 |
> 13 | const div = document.createElement('div');
| ^
14 |
15 | console.log(div);
16 |

at Object.document (__tests__/beforeTest.js:13:13)
`;
38 changes: 38 additions & 0 deletions e2e/__tests__/wrongEnv.test.ts
@@ -0,0 +1,38 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. 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.
*/

import wrap from 'jest-snapshot-serializer-raw';
import runJest from '../runJest';
import {extractSummary} from '../Utils';

function assertFailuresAndSnapshot(args: Array<string>) {
const result = runJest('wrong-env', args);
expect(result.exitCode).toBe(1);
expect(wrap(extractSummary(result.stderr).rest)).toMatchSnapshot();
}

describe('Wrong globals for environment', () => {
it('print useful error for window', () => {
assertFailuresAndSnapshot(['node', '-t=window']);
});

it('print useful error for document', () => {
assertFailuresAndSnapshot(['node', '-t=document']);
});

it('print useful error for navigator', () => {
assertFailuresAndSnapshot(['node', '-t=navigator']);
});

it('print useful error for unref', () => {
assertFailuresAndSnapshot(['jsdom', '-t=unref']);
});

it('print useful error when it explodes during evaluation', () => {
assertFailuresAndSnapshot(['beforeTest']);
});
});
17 changes: 17 additions & 0 deletions e2e/wrong-env/__tests__/beforeTest.js
@@ -0,0 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. 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.
*
* @jest-environment node
*
*/

/* eslint-env browser */

const div = document.createElement('div');

console.log(div);

test('stub', () => expect(1).toBe(1));
16 changes: 16 additions & 0 deletions e2e/wrong-env/__tests__/jsdom.js
@@ -0,0 +1,16 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. 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.
*
* @jest-environment jsdom
*/

'use strict';

test('use unref', () => {
setTimeout(() => {}, 0).unref();

expect(1).toBe(1);
});
37 changes: 37 additions & 0 deletions e2e/wrong-env/__tests__/node.js
@@ -0,0 +1,37 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. 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.
*
* @jest-environment node
*
*/

/* eslint-env browser */

'use strict';

test('use document', () => {
const div = document.createElement('div');

console.log(div);

expect(1).toBe(1);
});

test('use window', () => {
const location = window.location;

console.log(location);

expect(1).toBe(1);
});

test('use navigator', () => {
const userAgent = navigator.userAgent;

console.log(userAgent);

expect(1).toBe(1);
});
3 changes: 3 additions & 0 deletions e2e/wrong-env/package.json
@@ -0,0 +1,3 @@
{
"jest": {}
}
40 changes: 34 additions & 6 deletions packages/jest-message-util/src/index.ts
Expand Up @@ -92,6 +92,30 @@ const getRenderedCallsite = (

const blankStringRegexp = /^\s*$/;

function checkForCommonEnvironmentErrors(error: string) {
if (
error.includes('ReferenceError: document is not defined') ||
error.includes('ReferenceError: window is not defined') ||
error.includes('ReferenceError: navigator is not defined')
) {
return warnAboutWrongTestEnvironment(error, 'jsdom');
} else if (error.includes('.unref is not a function')) {
return warnAboutWrongTestEnvironment(error, 'node');
}

return error;
}

function warnAboutWrongTestEnvironment(error: string, env: 'jsdom' | 'node') {
return (
chalk.bold.red(
`The error below may be caused by using the wrong test environment, see ${chalk.dim.underline(
'https://jestjs.io/docs/en/configuration#testenvironment-string',
)}.\nConsider using the "${env}" test environment.\n\n`,
) + error
);
}

// ExecError is an error thrown outside of the test suite (not inside an `it` or
// `before/after each` hooks). If it's thrown, none of the tests in the file
// are executed.
Expand Down Expand Up @@ -126,6 +150,8 @@ export const formatExecError = (
message = separated.message;
}

message = checkForCommonEnvironmentErrors(message);

message = indentAllLines(message, MESSAGE_INDENT);

stack =
Expand Down Expand Up @@ -285,19 +311,21 @@ export const formatStackTrace = (
return `${renderedCallsite}\n${stacktrace}`;
};

type FailedResults = Array<{
content: string;
result: AssertionResult;
}>;

export const formatResultsErrors = (
testResults: Array<AssertionResult>,
config: StackTraceConfig,
options: StackTraceOptions,
testPath?: Path,
): string | null => {
type FailedResults = Array<{
content: string;
result: AssertionResult;
}>;

const failedResults: FailedResults = testResults.reduce((errors, result) => {
result.failureMessages.forEach(content => errors.push({content, result}));
result.failureMessages
.map(checkForCommonEnvironmentErrors)
.forEach(content => errors.push({content, result}));
return errors;
}, [] as FailedResults);

Expand Down