diff --git a/packages/angular/build/src/builders/dev-server/options.ts b/packages/angular/build/src/builders/dev-server/options.ts index 5473da832449..7dfdc56a371d 100644 --- a/packages/angular/build/src/builders/dev-server/options.ts +++ b/packages/angular/build/src/builders/dev-server/options.ts @@ -13,7 +13,12 @@ import { normalizeCacheOptions } from '../../utils/normalize-cache'; import { ApplicationBuilderOptions } from '../application'; import { Schema as DevServerOptions } from './schema'; -export type NormalizedDevServerOptions = Awaited>; +export type NormalizedDevServerOptions = Omit< + Awaited>, + 'strictPort' +> & { + strictPort?: boolean; +}; /** * Normalize the user provided options by creating full paths for all path based options @@ -122,6 +127,7 @@ export async function normalizeOptions( buildTarget, host: host ?? 'localhost', port, + strictPort: port !== 0, poll, open, verbose, diff --git a/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts b/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts index 9608e0dc976e..a17c0a198e14 100644 --- a/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts +++ b/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts @@ -38,8 +38,8 @@ describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupT expectNoLog(logs, 'Unexpected character "EOF"'); }, ], - { outputLogsOnFailure: false }, + { outputLogsOnFailure: false, timeout: 60_000 }, ); - }); + }, 90_000); }); }); diff --git a/packages/angular/build/src/builders/dev-server/vite/server.ts b/packages/angular/build/src/builders/dev-server/vite/server.ts index 7dd62aed37b6..fb7870bd2d27 100644 --- a/packages/angular/build/src/builders/dev-server/vite/server.ts +++ b/packages/angular/build/src/builders/dev-server/vite/server.ts @@ -56,7 +56,7 @@ async function createServerConfig( ssrFiles, }, port: serverOptions.port, - strictPort: true, + strictPort: serverOptions.strictPort ?? true, host: serverOptions.host, open: serverOptions.open, allowedHosts: serverOptions.allowedHosts, diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve-live-reload-proxies_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve-live-reload-proxies_spec.ts index 2ebd9e27d6c4..748fa01108af 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve-live-reload-proxies_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve-live-reload-proxies_spec.ts @@ -101,12 +101,33 @@ async function createProxy(target: string, secure: boolean, ws = true): Promise< }, }).listen(proxyPort); + server.on('error', () => { + // Ignore proxy connection errors that occur when the browser reloads or disconnects. + }); + return { server, url: `${secure ? 'https' : 'http'}://localhost:${proxyPort}`, }; } +async function waitForAppLiveReload(page: Page): Promise { + const startTime = Date.now(); + while (Date.now() - startTime < 30_000) { + try { + const text = await page.evaluate(() => document.querySelector('p')?.innerText); + if (text === 'app-live-reload') { + return; + } + } catch { + // Ignore execution context destruction errors during page navigation. + } + await setTimeoutPromise(100); + } + + throw new Error('Timed out waiting for page to reload with updated text.'); +} + async function goToPageAndWaitForWS(page: Page, url: string): Promise { const baseUrl = url.replace(/^http/, 'ws'); const socksRequest = baseUrl.at(-1) === '/' ? `${baseUrl}ng-cli-ws` : `${baseUrl}/ng-cli-ws`; @@ -203,8 +224,7 @@ describeServeBuilder( async ({ result }) => { expect(result?.success).toBeTrue(); - // Wait for page to reload. - await setTimeoutPromise(500); + await waitForAppLiveReload(page); const innerText = await page.evaluate(() => document.querySelector('p').innerText); expect(innerText).toBe('app-live-reload'); @@ -238,8 +258,7 @@ describeServeBuilder( async ({ result }) => { expect(result?.success).toBeTrue(); - // Wait for page to reload. - await setTimeoutPromise(500); + await waitForAppLiveReload(page); const innerText = await page.evaluate( () => document.querySelector('p').innerText, @@ -281,8 +300,7 @@ describeServeBuilder( async ({ result }) => { expect(result?.success).toBeTrue(); - // Wait for page to reload. - await setTimeoutPromise(500); + await waitForAppLiveReload(page); const innerText = await page.evaluate( () => document.querySelector('p').innerText,