Skip to content

Commit 1e72de0

Browse files
committed
fix(@angular/cli): fix error handling on test
Fix #2778 Fix #3424
1 parent a560646 commit 1e72de0

File tree

6 files changed

+81
-1
lines changed

6 files changed

+81
-1
lines changed

packages/@angular/cli/models/webpack-configs/test.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as webpack from 'webpack';
44

55
import { CliConfig } from '../config';
66
import { WebpackTestOptions } from '../webpack-test-config';
7+
import { KarmaWebpackEmitlessError } from '../../plugins/karma-webpack-emitless-error';
78

89
/**
910
* Enumerate loaders and their dependencies from this file to let the dependency validator
@@ -57,7 +58,8 @@ export function getTestConfig(testConfig: WebpackTestOptions) {
5758
new webpack.SourceMapDevToolPlugin({
5859
filename: null, // if no value is provided the sourcemap is inlined
5960
test: /\.(ts|js)($|\?)/i // process .js and .ts files only
60-
})
61+
}),
62+
new KarmaWebpackEmitlessError()
6163
]
6264
};
6365
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Don't emit anything when there are compilation errors. This is useful for preventing Karma
2+
// from re-running tests when there is a compilation error.
3+
// Workaround for https://github.com/webpack-contrib/karma-webpack/issues/49
4+
5+
export class KarmaWebpackEmitlessError {
6+
constructor() { }
7+
8+
apply(compiler: any): void {
9+
compiler.plugin('done', (stats: any) => {
10+
if (stats.compilation.errors.length > 0) {
11+
stats.stats = [{
12+
toJson: function () {
13+
return this;
14+
},
15+
assets: []
16+
}];
17+
}
18+
});
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Force Webpack to throw compilation errors. Useful with karma-webpack when in single-run mode.
2+
// Workaround for https://github.com/webpack-contrib/karma-webpack/issues/66
3+
4+
export class KarmaWebpackThrowError {
5+
constructor() { }
6+
7+
apply(compiler: any): void {
8+
compiler.plugin('done', (stats: any) => {
9+
if (stats.compilation.errors.length > 0) {
10+
throw new Error(stats.compilation.errors.map((err: any) => err.message || err));
11+
}
12+
});
13+
}
14+
}

packages/@angular/cli/plugins/karma.ts

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as glob from 'glob';
55
import { Pattern } from './glob-copy-webpack-plugin';
66
import { extraEntryParser } from '../models/webpack-configs/utils';
77
import { WebpackTestConfig, WebpackTestOptions } from '../models/webpack-test-config';
8+
import { KarmaWebpackThrowError } from './karma-webpack-throw-error';
89

910
const getAppFromConfig = require('../utilities/app-utils').getAppFromConfig;
1011

@@ -102,6 +103,11 @@ const init: any = (config: any) => {
102103
}
103104
};
104105

106+
// If Karma is being ran in single run mode, throw errors.
107+
if (config.singleRun) {
108+
webpackConfig.plugins.push(new KarmaWebpackThrowError());
109+
}
110+
105111
config.webpack = Object.assign(webpackConfig, config.webpack);
106112
config.webpackMiddleware = Object.assign(webpackMiddlewareConfig, config.webpackMiddleware);
107113

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { ng } from '../../utils/process';
2+
import { writeFile } from '../../utils/fs';
3+
import { expectToFail } from '../../utils/utils';
4+
5+
6+
export default function () {
7+
// Fails on single run with broken compilation.
8+
return writeFile('src/app.component.spec.ts', '<p> definitely not typescript </p>')
9+
.then(() => expectToFail(() => ng('test', '--single-run')));
10+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
killAllProcesses,
3+
waitForAnyProcessOutputToMatch,
4+
silentExecAndWaitForOutputToMatch
5+
} from '../../utils/process';
6+
import { expectToFail } from '../../utils/utils';
7+
import { readFile, writeFile } from '../../utils/fs';
8+
9+
10+
const karmaGoodRegEx = /Executed 3 of 3/;
11+
12+
export default function () {
13+
let originalSpec: string;
14+
return silentExecAndWaitForOutputToMatch('ng', ['test'], karmaGoodRegEx)
15+
.then(() => readFile('src/app.component.spec.ts'))
16+
.then((data) => originalSpec = data)
17+
// Trigger a failed rebuild, which shouldn't run tests again.
18+
.then(() => writeFile('src/app.component.spec.ts', '<p> definitely not typescript </p>'))
19+
.then(() => expectToFail(() => waitForAnyProcessOutputToMatch(karmaGoodRegEx, 10000)))
20+
// Restore working spec.
21+
.then(() => writeFile('src/app.component.spec.ts', originalSpec))
22+
.then(() => waitForAnyProcessOutputToMatch(karmaGoodRegEx, 10000))
23+
.then(() => killAllProcesses(), (err: any) => {
24+
killAllProcesses();
25+
throw err;
26+
});
27+
}
28+

0 commit comments

Comments
 (0)