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

Lines changed: 20 additions & 3 deletions
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

Lines changed: 25 additions & 24 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy