Skip to content

Commit

Permalink
make watch plugin initialization errors look nice (#8422)
Browse files Browse the repository at this point in the history
* make watch plugin initialization errors look nice

* Update CHANGELOG.md

* remove absolute path from snapshot

* review feedback

* review and CI

* CI

* try slash to fix Windows CI
  • Loading branch information
jeysal committed May 7, 2019
1 parent aca4861 commit 2297194
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
### Fixes

- `[babel-plugin-jest-hoist]` Expand list of whitelisted globals in global mocks ([#8429](https://github.com/facebook/jest/pull/8429)
- `[jest-core]` Make watch plugin initialization errors look nice ([#8422](https://github.com/facebook/jest/pull/8422))

### Chore & Maintenance

Expand Down
7 changes: 6 additions & 1 deletion packages/jest-cli/src/cli/index.ts
Expand Up @@ -36,7 +36,12 @@ export async function run(maybeArgv?: Array<string>, project?: Config.Path) {
} catch (error) {
clearLine(process.stderr);
clearLine(process.stdout);
console.error(chalk.red(error.stack));
if (error.stack) {
console.error(chalk.red(error.stack));
} else {
console.error(chalk.red(error));
}

exit(1);
throw error;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-core/package.json
Expand Up @@ -31,6 +31,7 @@
"pirates": "^4.0.1",
"realpath-native": "^1.1.0",
"rimraf": "^2.5.4",
"slash": "^2.0.0",
"strip-ansi": "^5.0.0"
},
"devDependencies": {
Expand All @@ -41,6 +42,7 @@
"@types/micromatch": "^3.1.0",
"@types/p-each-series": "^1.0.0",
"@types/rimraf": "^2.0.2",
"@types/slash": "^2.0.0",
"@types/strip-ansi": "^3.0.0"
},
"engines": {
Expand Down
@@ -0,0 +1,3 @@
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.

throw new Error('initialization error');
11 changes: 11 additions & 0 deletions packages/jest-core/src/__tests__/__snapshots__/watch.test.js.snap
Expand Up @@ -50,6 +50,17 @@ Watch Usage
]
`;

exports[`Watch mode flows makes watch plugin initialization errors look nice 1`] = `
[Error: Failed to initialize watch plugin "packages/jest-core/src/__tests__/__fixtures__/watch_plugin_throws":
● Test suite failed to run
initialization error
at Object.<anonymous> (__fixtures__/watch_plugin_throws.js:3:7)
]
`;
exports[`Watch mode flows shows prompts for WatchPlugins in alphabetical order 1`] = `
Array [
Array [
Expand Down
25 changes: 24 additions & 1 deletion packages/jest-core/src/__tests__/watch.test.js
Expand Up @@ -108,7 +108,12 @@ describe('Watch mode flows', () => {
isInteractive = true;
jest.doMock('jest-util/build/isInteractive', () => isInteractive);
watch = require('../watch').default;
const config = {roots: [], testPathIgnorePatterns: [], testRegex: []};
const config = {
rootDir: __dirname,
roots: [],
testPathIgnorePatterns: [],
testRegex: [],
};
pipe = {write: jest.fn()};
globalConfig = {watch: true};
hasteMapInstances = [{on: () => {}}];
Expand Down Expand Up @@ -571,6 +576,24 @@ describe('Watch mode flows', () => {
});
});

it('makes watch plugin initialization errors look nice', async () => {
const pluginPath = `${__dirname}/__fixtures__/watch_plugin_throws`;

await expect(
watch(
{
...globalConfig,
rootDir: __dirname,
watchPlugins: [{config: {}, path: pluginPath}],
},
contexts,
pipe,
hasteMapInstances,
stdin,
),
).rejects.toMatchSnapshot();
});

it.each`
ok | option
${'✔︎'} | ${'bail'}
Expand Down
27 changes: 21 additions & 6 deletions packages/jest-core/src/watch.ts
Expand Up @@ -5,9 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/

import path from 'path';
import ansiEscapes from 'ansi-escapes';
import chalk from 'chalk';
import exit from 'exit';
import slash from 'slash';
import HasteMap, {HasteChangeEvent} from 'jest-haste-map';
import {formatExecError} from 'jest-message-util';
import {isInteractive, preRunMessage, specialChars} from 'jest-util';
Expand Down Expand Up @@ -171,12 +173,25 @@ export default function watch(
}

for (const pluginWithConfig of globalConfig.watchPlugins) {
const ThirdPartyPlugin = require(pluginWithConfig.path);
const plugin: WatchPlugin = new ThirdPartyPlugin({
config: pluginWithConfig.config,
stdin,
stdout: outputStream,
});
let plugin: WatchPlugin;
try {
const ThirdPartyPlugin = require(pluginWithConfig.path);
plugin = new ThirdPartyPlugin({
config: pluginWithConfig.config,
stdin,
stdout: outputStream,
});
} catch (error) {
const errorWithContext = new Error(
`Failed to initialize watch plugin "${chalk.bold(
slash(path.relative(process.cwd(), pluginWithConfig.path)),
)}":\n\n${formatExecError(error, contexts[0].config, {
noStackTrace: false,
})}`,
);
delete errorWithContext.stack;
return Promise.reject(errorWithContext);
}
checkForConflicts(watchPluginKeys, plugin, globalConfig);

const hookSubscriber = hooks.getSubscriber();
Expand Down

0 comments on commit 2297194

Please sign in to comment.