From 6a617ff4a2fe75968965dc5dcf0f3ba7bae92935 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 11 Jan 2022 08:31:36 +0100 Subject: [PATCH] fix(@angular-devkit/build-angular): ensure `$localize` calls are replaced in watch mode When `translations` is undefined `$localize` calls are not replaced. https://github.com/angular/angular-cli/blob/2c9a33dddb38694b6940ec6981c49904de1ab636/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts#L382 Closes #22435 (cherry picked from commit 426ddb68d9a21b036d6151e6cdee625e58ca1194) --- .../src/builders/dev-server/index.ts | 2 +- .../build_localize_replaced_watch_spec.ts | 82 +++++++++++++++++++ .../src/builders/dev-server/tests/setup.ts | 2 +- 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts index 5a19d8002ba8..87e48524573c 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts @@ -378,7 +378,7 @@ async function setupLocalize( addError(compilation, message); }, }); - i18nLoaderOptions.translation = localeDescription.translation; + i18nLoaderOptions.translation = localeDescription.translation ?? {}; } compilation.hooks.finishModules.tap('build-angular', () => { diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts new file mode 100644 index 000000000000..5ada84dcc828 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts @@ -0,0 +1,82 @@ +/** + * @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 + */ + +/* eslint-disable max-len */ +import fetch from 'node-fetch'; // eslint-disable-line import/no-extraneous-dependencies +import { concatMap, count, take, timeout } from 'rxjs/operators'; +import { URL } from 'url'; +import { serveWebpackBrowser } from '../../index'; +import { + BASE_OPTIONS, + BUILD_TIMEOUT, + DEV_SERVER_BUILDER_INFO, + describeBuilder, + setupBrowserTarget, +} from '../setup'; + +describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { + describe('Behavior: "i18n $localize calls are replaced during watching"', () => { + beforeEach(() => { + harness.useProject('test', { + root: '.', + sourceRoot: 'src', + cli: { + cache: { + enabled: false, + }, + }, + i18n: { + sourceLocale: { + 'code': 'fr', + }, + }, + }); + + setupBrowserTarget(harness, { localize: ['fr'] }); + }); + + it('$localize are replaced in watch', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + await harness.writeFile( + 'src/app/app.component.html', + ` +

Hello {{ title }}!

+ `, + ); + + const buildCount = await harness + .execute() + .pipe( + timeout(BUILD_TIMEOUT), + concatMap(async ({ result }, index) => { + expect(result?.success).toBe(true); + + const response = await fetch(new URL('main.js', `${result?.baseUrl}`)); + expect(await response?.text()).not.toContain('$localize`:'); + + switch (index) { + case 0: { + await harness.modifyFile('src/app/app.component.html', (content) => + content.replace('introduction', 'intro'), + ); + break; + } + } + }), + take(2), + count(), + ) + .toPromise(); + + expect(buildCount).toBe(2); + }); + }); +}); diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts index 92cd146a40c4..a6330da2a7cb 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts @@ -38,7 +38,7 @@ export const BASE_OPTIONS = Object.freeze({ * Maximum time for single build/rebuild * This accounts for CI variability. */ -export const BUILD_TIMEOUT = 15000; +export const BUILD_TIMEOUT = 15_000; /** * Cached browser builder option schema