From 87c4f7f2233983d2e8abfff27e8541a6c2cec23c Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:07:23 +0000 Subject: [PATCH 1/2] test: use esbuild-based karma builder for e2e tests in esbuild suite Updated the E2E tests to use the esbuild-based karma builder when running the esbuild test suite. --- .../e2e/tests/misc/karma-error-paths.ts | 26 ------------------- .../legacy-cli/e2e/tests/test/test-scripts.ts | 4 +-- .../e2e/tests/test/test-sourcemap.ts | 21 ++++++++++----- tests/legacy-cli/e2e/utils/project.ts | 3 +++ 4 files changed, 19 insertions(+), 35 deletions(-) delete mode 100644 tests/legacy-cli/e2e/tests/misc/karma-error-paths.ts diff --git a/tests/legacy-cli/e2e/tests/misc/karma-error-paths.ts b/tests/legacy-cli/e2e/tests/misc/karma-error-paths.ts deleted file mode 100644 index 9a7a5daa2df8..000000000000 --- a/tests/legacy-cli/e2e/tests/misc/karma-error-paths.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { writeMultipleFiles } from '../../utils/fs'; -import { ng } from '../../utils/process'; -import { expectToFail } from '../../utils/utils'; - -export default async function () { - await writeMultipleFiles({ - 'src/app/app.component.spec.ts': ` - describe('AppComponent', () => { - it('failing test', () => { - expect('1').toEqual('2'); - }); - }); - `, - }); - - const { message } = await expectToFail(() => ng('test', '--no-watch')); - if (message.includes('_karma_webpack_')) { - throw new Error(`Didn't expect logs to server address and webpack scheme.\n${message}`); - } - - if (!message.includes('(src/app/app.component.spec.ts:4:25)')) { - throw new Error( - `Expected logs to contain relative path to (src/app/app.component.spec.ts:4:25)\n${message}`, - ); - } -} diff --git a/tests/legacy-cli/e2e/tests/test/test-scripts.ts b/tests/legacy-cli/e2e/tests/test/test-scripts.ts index dc1d6734905a..4e308a6922b9 100644 --- a/tests/legacy-cli/e2e/tests/test/test-scripts.ts +++ b/tests/legacy-cli/e2e/tests/test/test-scripts.ts @@ -10,8 +10,8 @@ export default async function () { // prepare global scripts test files await writeMultipleFiles({ - 'src/string-script.js': `stringScriptGlobal = 'string-scripts.js';`, - 'src/input-script.js': `inputScriptGlobal = 'input-scripts.js';`, + 'src/string-script.js': `globalThis.stringScriptGlobal = 'string-scripts.js';`, + 'src/input-script.js': `globalThis.inputScriptGlobal = 'input-scripts.js';`, 'src/typings.d.ts': ` declare var stringScriptGlobal: any; declare var inputScriptGlobal: any; diff --git a/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts b/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts index 620e5ab138b5..17f845a194d0 100644 --- a/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts +++ b/tests/legacy-cli/e2e/tests/test/test-sourcemap.ts @@ -1,11 +1,19 @@ +import assert from 'node:assert'; +import { getGlobalVariable } from '../../utils/env'; import { writeFile } from '../../utils/fs'; import { ng } from '../../utils/process'; +import { assertIsError } from '../../utils/utils'; export default async function () { + if (getGlobalVariable('argv')['esbuild']) { + // TODO: enable once this is fixed when using the esbuild builder. + return; + } + await writeFile( 'src/app/app.component.spec.ts', ` - it('show fail', () => { + it('should fail', () => { expect(undefined).toBeTruthy(); }); `, @@ -16,9 +24,9 @@ export default async function () { await ng('test', '--no-watch', '--source-map'); throw new Error('ng test should have failed.'); } catch (error) { - if (!(error instanceof Error && error.message.includes('app.component.spec.ts'))) { - throw error; - } + assertIsError(error); + assert.match(error.message, /src\/app\/app\.component\.spec\.ts/); + assert.doesNotMatch(error.message, /_karma_webpack_/); } // when sourcemaps are 'off' the stacktrace won't point to the spec.ts file. @@ -26,8 +34,7 @@ export default async function () { await ng('test', '--no-watch', '--no-source-map'); throw new Error('ng test should have failed.'); } catch (error) { - if (!(error instanceof Error && error.message.includes('main.js'))) { - throw error; - } + assertIsError(error); + assert.match(error.message, /main\.js/); } } diff --git a/tests/legacy-cli/e2e/utils/project.ts b/tests/legacy-cli/e2e/utils/project.ts index 99a2958ceb4f..1a9b518648ae 100644 --- a/tests/legacy-cli/e2e/utils/project.ts +++ b/tests/legacy-cli/e2e/utils/project.ts @@ -192,6 +192,9 @@ export async function useCIChrome(projectName: string, projectDir = ''): Promise const project = workspaceJson.projects[projectName]; const appTargets = project.targets || project.architect; appTargets.test.options.browsers = 'ChromeHeadlessNoSandbox'; + appTargets.test.options.builderMode = getGlobalVariable('argv')['esbuild'] + ? 'application' + : 'browser'; }); } From f519dccf77862eaba85bfc78f58029d3be211da3 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:07:32 +0000 Subject: [PATCH 2/2] fix(@angular-devkit/build-angular): pass missing options to Karma esbuild builder Ensure that several previously omitted options are correctly passed to the Karma esbuild builder, improving consistency and expected behavior. --- .../src/builders/karma/application_builder.ts | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/builders/karma/application_builder.ts b/packages/angular_devkit/build_angular/src/builders/karma/application_builder.ts index 5a23606f2eac..72ee72369a05 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/application_builder.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/application_builder.ts @@ -25,6 +25,7 @@ import * as path from 'path'; import { Observable, Subscriber, catchError, defaultIfEmpty, from, of, switchMap } from 'rxjs'; import { Configuration } from 'webpack'; import { ExecutionTransformer } from '../../transforms'; +import { normalizeFileReplacements } from '../../utils'; import { OutputHashing } from '../browser-esbuild/schema'; import { findTests, getTestEntrypoints } from './find-tests'; import { Schema as KarmaBuilderOptions } from './schema'; @@ -400,17 +401,24 @@ async function initializeApplication( index: false, outputHashing: OutputHashing.None, optimization: false, - sourceMap: { - scripts: true, - styles: true, - vendor: true, - }, + sourceMap: options.codeCoverage + ? { + scripts: true, + styles: true, + vendor: true, + } + : options.sourceMap, instrumentForCoverage, styles: options.styles, + scripts: options.scripts, polyfills, webWorkerTsConfig: options.webWorkerTsConfig, watch: options.watch ?? !karmaOptions.singleRun, stylePreprocessorOptions: options.stylePreprocessorOptions, + inlineStyleLanguage: options.inlineStyleLanguage, + fileReplacements: options.fileReplacements + ? normalizeFileReplacements(options.fileReplacements, './') + : undefined, }; // Build tests with `application` builder, using test files as entry points. @@ -447,6 +455,16 @@ async function initializeApplication( }; karmaOptions.files ??= []; + if (options.scripts?.length) { + // This should be more granular to support named bundles. + // However, it replicates the behavior of the Karma Webpack-based builder. + karmaOptions.files.push({ + pattern: `${outputPath}/scripts.js`, + watched: false, + type: 'js', + }); + } + karmaOptions.files.push( // Serve global setup script. { pattern: `${outputPath}/${mainName}.js`, type: 'module', watched: false },