-
Notifications
You must be signed in to change notification settings - Fork 12k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(@angular-devkit/build-angular): fully track Web Worker file chang…
…es in watch mode When using the application builder with a Web Worker in watch mode, A change to the Web Worker code will now invalidate the referencing source file to ensure that all changes are captured and the new output file for the Web Worker is correctly injected into the referencing output file. Previously, the Web Worker output file may have changed but the reference may not have been updated causing an old instance of the Web worker code to be used in watch mode. (cherry picked from commit 1ed3a16)
- Loading branch information
Showing
5 changed files
with
298 additions
and
48 deletions.
There are no files selected for viewing
123 changes: 123 additions & 0 deletions
123
..._devkit/build_angular/src/builders/application/tests/behavior/rebuild-web-workers_spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import { logging } from '@angular-devkit/core'; | ||
import { concatMap, count, take, timeout } from 'rxjs'; | ||
import { buildApplication } from '../../index'; | ||
import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup'; | ||
|
||
/** | ||
* Maximum time in milliseconds for single build/rebuild | ||
* This accounts for CI variability. | ||
*/ | ||
export const BUILD_TIMEOUT = 30_000; | ||
|
||
describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { | ||
describe('Behavior: "Rebuilds when Web Worker files change"', () => { | ||
it('Recovers from error when directly referenced worker file is changed', async () => { | ||
harness.useTarget('build', { | ||
...BASE_OPTIONS, | ||
watch: true, | ||
}); | ||
|
||
const workerCodeFile = ` | ||
console.log('WORKER FILE'); | ||
`; | ||
|
||
const errorText = `Expected ";" but found "~"`; | ||
|
||
// Create a worker file | ||
await harness.writeFile('src/app/worker.ts', workerCodeFile); | ||
|
||
// Create app component that uses the directive | ||
await harness.writeFile( | ||
'src/app/app.component.ts', | ||
` | ||
import { Component } from '@angular/core' | ||
@Component({ | ||
selector: 'app-root', | ||
template: '<h1>Worker Test</h1>', | ||
}) | ||
export class AppComponent { | ||
worker = new Worker(new URL('./worker', import.meta.url), { type: 'module' }); | ||
} | ||
`, | ||
); | ||
|
||
const builderAbort = new AbortController(); | ||
const buildCount = await harness | ||
.execute({ outputLogsOnFailure: false, signal: builderAbort.signal }) | ||
.pipe( | ||
timeout(BUILD_TIMEOUT), | ||
concatMap(async ({ result, logs }, index) => { | ||
switch (index) { | ||
case 0: | ||
expect(result?.success).toBeTrue(); | ||
|
||
// Update the worker file to be invalid syntax | ||
await harness.writeFile('src/app/worker.ts', `asd;fj$3~kls;kd^(*fjlk;sdj---flk`); | ||
|
||
break; | ||
case 1: | ||
expect(logs).toContain( | ||
jasmine.objectContaining<logging.LogEntry>({ | ||
message: jasmine.stringMatching(errorText), | ||
}), | ||
); | ||
|
||
// Make an unrelated change to verify error cache was updated | ||
// Should persist error in the next rebuild | ||
await harness.modifyFile('src/main.ts', (content) => content + '\n'); | ||
|
||
break; | ||
case 2: | ||
expect(logs).toContain( | ||
jasmine.objectContaining<logging.LogEntry>({ | ||
message: jasmine.stringMatching(errorText), | ||
}), | ||
); | ||
|
||
// Revert the change that caused the error | ||
// Should remove the error | ||
await harness.writeFile('src/app/worker.ts', workerCodeFile); | ||
|
||
break; | ||
case 3: | ||
expect(result?.success).toBeTrue(); | ||
expect(logs).not.toContain( | ||
jasmine.objectContaining<logging.LogEntry>({ | ||
message: jasmine.stringMatching(errorText), | ||
}), | ||
); | ||
|
||
// Make an unrelated change to verify error cache was updated | ||
// Should continue showing no error | ||
await harness.modifyFile('src/main.ts', (content) => content + '\n'); | ||
|
||
break; | ||
case 4: | ||
expect(result?.success).toBeTrue(); | ||
expect(logs).not.toContain( | ||
jasmine.objectContaining<logging.LogEntry>({ | ||
message: jasmine.stringMatching(errorText), | ||
}), | ||
); | ||
|
||
// Test complete - abort watch mode | ||
builderAbort?.abort(); | ||
break; | ||
} | ||
}), | ||
count(), | ||
) | ||
.toPromise(); | ||
|
||
expect(buildCount).toBe(5); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.