From fdce97fbf260d10687de227149699b961ce7f47b Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:08:57 -0400 Subject: [PATCH] test(@angular/build): add e2e test for animations chunk optimization Add an E2E test case to verify that the chunk optimizer does not fold lazy-loaded animations modules back into the primary main chunk. The test installs the matching version of @angular/animations, injects provideAnimationsAsync, and builds the test project with chunk optimization enabled. It then validates that the AnimationEngine is preserved within one of the independent lazy chunks and is absent from the initial main.js output. --- .../builders/application/chunk-optimizer.ts | 1 + tests/e2e.bzl | 1 + .../tests/build/chunk-optimizer-animations.ts | 74 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 tests/e2e/tests/build/chunk-optimizer-animations.ts diff --git a/packages/angular/build/src/builders/application/chunk-optimizer.ts b/packages/angular/build/src/builders/application/chunk-optimizer.ts index 4d72606640f7..5898c95401ee 100644 --- a/packages/angular/build/src/builders/application/chunk-optimizer.ts +++ b/packages/angular/build/src/builders/application/chunk-optimizer.ts @@ -312,6 +312,7 @@ export async function optimizeChunks( }); const result = await bundle.generate({ + compact: true, sourcemap, chunkFileNames: (chunkInfo) => `${chunkInfo.name.replace(/-[a-zA-Z0-9]{8}$/, '')}-[hash].js`, diff --git a/tests/e2e.bzl b/tests/e2e.bzl index 2c80375c580f..95f4d7a8c435 100644 --- a/tests/e2e.bzl +++ b/tests/e2e.bzl @@ -59,6 +59,7 @@ WEBPACK_IGNORE_TESTS = [ "tests/build/chunk-optimizer-lazy.js", "tests/build/chunk-optimizer-heuristic.js", "tests/build/chunk-optimizer-env.js", + "tests/build/chunk-optimizer-animations.js", ] def _to_glob(patterns): diff --git a/tests/e2e/tests/build/chunk-optimizer-animations.ts b/tests/e2e/tests/build/chunk-optimizer-animations.ts new file mode 100644 index 000000000000..158c0a2ec474 --- /dev/null +++ b/tests/e2e/tests/build/chunk-optimizer-animations.ts @@ -0,0 +1,74 @@ +import assert from 'node:assert/strict'; +import { readdir } from 'node:fs/promises'; +import { readFile, writeFile } from '../../utils/fs'; +import { installPackage } from '../../utils/packages'; +import { execWithEnv } from '../../utils/process'; + +export default async function () { + // Read @angular/core version from test project's package.json + const projectJson = JSON.parse(await readFile('package.json')); + const ngCoreVersion = + projectJson.dependencies?.['@angular/core'] ?? + projectJson.devDependencies?.['@angular/core'] ?? + 'latest'; + + // Install @angular/animations package with matching version + await installPackage(`@angular/animations@${ngCoreVersion}`); + + // Configure app.config.ts with provideAnimationsAsync + const originalConfig = await readFile('src/app/app.config.ts'); + await writeFile( + 'src/app/app.config.ts', + ` + import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; + ${originalConfig.replace(/providers:\s*\[/, 'providers: [provideAnimationsAsync(),')} + `, + ); + + const updatedConfig = await readFile('src/app/app.config.ts'); + assert.ok( + updatedConfig.includes('provideAnimationsAsync()'), + 'Expected src/app/app.config.ts to include provideAnimationsAsync().', + ); + + // Build with chunk optimization + await execWithEnv('ng', ['build', '--output-hashing=none'], { + ...process.env, + NG_BUILD_OPTIMIZE_CHUNKS: '1', + }); + const optimizedFiles = await readdir('dist/test-project/browser'); + const optimizedJsFiles = optimizedFiles.filter((f) => f.endsWith('.js')); + + // Read the optimized main.js file + const mainCode = await readFile('dist/test-project/browser/main.js'); + + // Check that optimized chunks still contain more than 1 javascript file + assert.ok( + optimizedJsFiles.length > 1, + `Expected more than one chunk, but found ${optimizedJsFiles.length}.`, + ); + + // Check that one of the lazy loaded chunks contains the animations package code + let foundAnimationsChunk = false; + for (const file of optimizedJsFiles) { + if (file === 'main.js') { + continue; + } + const code = await readFile(`dist/test-project/browser/${file}`); + if (code.includes('AnimationEngine')) { + foundAnimationsChunk = true; + break; + } + } + + assert.ok( + foundAnimationsChunk, + 'Expected to find AnimationEngine in one of the optimized lazy chunks.', + ); + + // The animations engine should not be bundled in main.js + assert.ok( + !mainCode.includes('AnimationEngine'), + 'Expected main.js not to contain AnimationEngine from @angular/animations/browser.', + ); +}