Skip to content

Commit

Permalink
feat: check for common errors when using the wrong test environment (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Mar 28, 2020
1 parent b7cd432 commit 2a4b073
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 6 deletions.
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

0 comments on commit 2a4b073

Please sign in to comment.