Skip to content

Commit ccc8e03

Browse files
alan-agius4clydin
authored andcommitted
fix(@angular-devkit/build-angular): display actionable error when a style does not exist in Karma builder
Prior to this change the the error was not displayed correctly due to compilation being undefined. Closes #24416 (cherry picked from commit 8fd0849)
1 parent 507f756 commit ccc8e03

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

packages/angular_devkit/build_angular/src/builders/karma/tests/options/styles_spec.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => {
1616
'src/styles.css': 'p {display: none}',
1717
'src/app/app.component.ts': `
1818
import { Component } from '@angular/core';
19-
19+
2020
@Component({
2121
selector: 'app-root',
2222
template: '<p>Hello World</p>'
@@ -27,7 +27,7 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => {
2727
'src/app/app.component.spec.ts': `
2828
import { TestBed } from '@angular/core/testing';
2929
import { AppComponent } from './app.component';
30-
30+
3131
describe('AppComponent', () => {
3232
beforeEach(async () => {
3333
await TestBed.configureTestingModule({
@@ -38,7 +38,7 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => {
3838
]
3939
}).compileComponents();
4040
});
41-
41+
4242
it('should not contain text that is hidden via css', () => {
4343
const fixture = TestBed.createComponent(AppComponent);
4444
expect(fixture.nativeElement.innerText).not.toContain('Hello World');
@@ -129,5 +129,22 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => {
129129
const { result } = await harness.executeOnce();
130130
expect(result?.success).toBeTrue();
131131
});
132+
133+
it('fails and shows an error if style does not exist', async () => {
134+
harness.useTarget('test', {
135+
...BASE_OPTIONS,
136+
styles: ['src/test-style-a.css'],
137+
});
138+
139+
const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });
140+
141+
expect(result?.success).toBeFalse();
142+
expect(logs).toContain(
143+
jasmine.objectContaining({
144+
level: 'error',
145+
message: jasmine.stringMatching(`Can't resolve 'src/test-style-a.css'`),
146+
}),
147+
);
148+
});
132149
});
133150
});

packages/angular_devkit/build_angular/src/webpack/plugins/styles-webpack-plugin.ts

+25-24
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
import assert from 'assert';
10-
import { pluginName } from 'mini-css-extract-plugin';
1110
import type { Compilation, Compiler } from 'webpack';
1211
import { assertIsError } from '../../utils/error';
1312
import { addError } from '../../utils/webpack-diagnostics';
@@ -30,10 +29,6 @@ export class StylesWebpackPlugin {
3029

3130
apply(compiler: Compiler): void {
3231
const { entryPoints, preserveSymlinks, root } = this.options;
33-
const webpackOptions = compiler.options;
34-
const entry =
35-
typeof webpackOptions.entry === 'function' ? webpackOptions.entry() : webpackOptions.entry;
36-
3732
const resolver = compiler.resolverFactory.get('global-styles', {
3833
conditionNames: ['sass', 'less', 'style'],
3934
mainFields: ['sass', 'less', 'style', 'main', '...'],
@@ -45,32 +40,38 @@ export class StylesWebpackPlugin {
4540
fileSystem: compiler.inputFileSystem,
4641
});
4742

48-
webpackOptions.entry = async () => {
49-
const entrypoints = await entry;
43+
const webpackOptions = compiler.options;
44+
compiler.hooks.environment.tap(PLUGIN_NAME, () => {
45+
const entry =
46+
typeof webpackOptions.entry === 'function' ? webpackOptions.entry() : webpackOptions.entry;
5047

51-
for (const [bundleName, paths] of Object.entries(entryPoints)) {
52-
entrypoints[bundleName] ??= {};
53-
const entryImport = (entrypoints[bundleName].import ??= []);
48+
webpackOptions.entry = async () => {
49+
const entrypoints = await entry;
5450

55-
for (const path of paths) {
56-
try {
57-
const resolvedPath = resolver.resolveSync({}, root, path);
58-
if (resolvedPath) {
59-
entryImport.push(`${resolvedPath}?ngGlobalStyle`);
60-
} else {
51+
for (const [bundleName, paths] of Object.entries(entryPoints)) {
52+
entrypoints[bundleName] ??= {};
53+
const entryImport = (entrypoints[bundleName].import ??= []);
54+
55+
for (const path of paths) {
56+
try {
57+
const resolvedPath = resolver.resolveSync({}, root, path);
58+
if (resolvedPath) {
59+
entryImport.push(`${resolvedPath}?ngGlobalStyle`);
60+
} else {
61+
assert(this.compilation, 'Compilation cannot be undefined.');
62+
addError(this.compilation, `Cannot resolve '${path}'.`);
63+
}
64+
} catch (error) {
6165
assert(this.compilation, 'Compilation cannot be undefined.');
62-
addError(this.compilation, `Cannot resolve '${path}'.`);
66+
assertIsError(error);
67+
addError(this.compilation, error.message);
6368
}
64-
} catch (error) {
65-
assert(this.compilation, 'Compilation cannot be undefined.');
66-
assertIsError(error);
67-
addError(this.compilation, error.message);
6869
}
6970
}
70-
}
7171

72-
return entrypoints;
73-
};
72+
return entrypoints;
73+
};
74+
});
7475

7576
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
7677
this.compilation = compilation;

0 commit comments

Comments
 (0)