-
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/build): ensure recreated files are watched
When deleting a file and then recreating a file that is again referenced in the application, the watch state will now be correctly synchronized. Previously the application builder would consider the previously deleted file as still watched which would prevent it from being watched again. This situation can happen when switching source control branches while a build is active watching. (cherry picked from commit 8cff5e7)
- Loading branch information
Showing
2 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
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
111 changes: 111 additions & 0 deletions
111
packages/angular/build/src/builders/application/tests/behavior/rebuild-general_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,111 @@ | ||
/** | ||
* @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 { 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: "Rebuild updates in general cases"', () => { | ||
it('detects changes after a file was deleted and recreated', async () => { | ||
harness.useTarget('build', { | ||
...BASE_OPTIONS, | ||
watch: true, | ||
}); | ||
|
||
const fileAContent = ` | ||
console.log('FILE-A'); | ||
export {}; | ||
`; | ||
|
||
// Create a file and add to application | ||
await harness.writeFile('src/app/file-a.ts', fileAContent); | ||
await harness.writeFile( | ||
'src/app/app.component.ts', | ||
` | ||
import { Component } from '@angular/core'; | ||
import './file-a'; | ||
@Component({ | ||
selector: 'app-root', | ||
template: 'App component', | ||
}) | ||
export class AppComponent { } | ||
`, | ||
); | ||
|
||
const buildCount = await harness | ||
.execute({ outputLogsOnFailure: false }) | ||
.pipe( | ||
timeout(BUILD_TIMEOUT), | ||
concatMap(async ({ result, logs }, index) => { | ||
switch (index) { | ||
case 0: | ||
expect(result?.success).toBeTrue(); | ||
harness.expectFile('dist/browser/main.js').content.toContain('FILE-A'); | ||
|
||
// Delete the imported file | ||
await harness.removeFile('src/app/file-a.ts'); | ||
|
||
break; | ||
case 1: | ||
// Should fail from missing import | ||
expect(result?.success).toBeFalse(); | ||
|
||
// Remove the failing import | ||
await harness.modifyFile('src/app/app.component.ts', (content) => | ||
content.replace(`import './file-a';`, ''), | ||
); | ||
|
||
break; | ||
case 2: | ||
expect(result?.success).toBeTrue(); | ||
|
||
harness.expectFile('dist/browser/main.js').content.not.toContain('FILE-A'); | ||
|
||
// Recreate the file and the import | ||
await harness.writeFile('src/app/file-a.ts', fileAContent); | ||
await harness.modifyFile( | ||
'src/app/app.component.ts', | ||
(content) => `import './file-a';\n` + content, | ||
); | ||
|
||
break; | ||
case 3: | ||
expect(result?.success).toBeTrue(); | ||
|
||
harness.expectFile('dist/browser/main.js').content.toContain('FILE-A'); | ||
|
||
// Change the imported file | ||
await harness.modifyFile('src/app/file-a.ts', (content) => | ||
content.replace('FILE-A', 'FILE-B'), | ||
); | ||
|
||
break; | ||
case 4: | ||
expect(result?.success).toBeTrue(); | ||
|
||
harness.expectFile('dist/browser/main.js').content.toContain('FILE-B'); | ||
|
||
break; | ||
} | ||
}), | ||
take(5), | ||
count(), | ||
) | ||
.toPromise(); | ||
|
||
expect(buildCount).toBe(5); | ||
}); | ||
}); | ||
}); |