From 266b84718160310c0bd56ca268ccbf38617e9326 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:11:38 +0000 Subject: [PATCH 1/3] feat: replace `@angular/platform-browser-dynamic` with `@angular/platform-browser` for Angular 20 --- .../apps/app1/src/app/demo/demo-main.ts | 4 +-- .../example-app-v18/src/app/demo/demo-main.ts | 4 +-- .../example-app-v19/src/app/demo/demo-main.ts | 4 +-- .../example-app-v20/src/app/demo/demo-main.ts | 4 +-- package.json | 1 + setup-env/zone/index.js | 27 ++++++++++++---- setup-env/zone/index.mjs | 27 ++++++++++++---- setup-env/zoneless/index.js | 32 +++++++++++++------ setup-env/zoneless/index.mjs | 32 +++++++++++++------ src/config/setup-env.spec.ts | 17 ++++++++-- website/src/pages/index.tsx | 1 - yarn.lock | 1 + 12 files changed, 112 insertions(+), 42 deletions(-) diff --git a/examples/example-app-monorepo/apps/app1/src/app/demo/demo-main.ts b/examples/example-app-monorepo/apps/app1/src/app/demo/demo-main.ts index 15f8809662..942af0017f 100644 --- a/examples/example-app-monorepo/apps/app1/src/app/demo/demo-main.ts +++ b/examples/example-app-monorepo/apps/app1/src/app/demo/demo-main.ts @@ -1,5 +1,5 @@ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { platformBrowser } from '@angular/platform-browser'; import { demoProviders } from './demo'; -platformBrowserDynamic([demoProviders]); +platformBrowser([demoProviders]); diff --git a/examples/example-app-v18/src/app/demo/demo-main.ts b/examples/example-app-v18/src/app/demo/demo-main.ts index 15f8809662..942af0017f 100644 --- a/examples/example-app-v18/src/app/demo/demo-main.ts +++ b/examples/example-app-v18/src/app/demo/demo-main.ts @@ -1,5 +1,5 @@ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { platformBrowser } from '@angular/platform-browser'; import { demoProviders } from './demo'; -platformBrowserDynamic([demoProviders]); +platformBrowser([demoProviders]); diff --git a/examples/example-app-v19/src/app/demo/demo-main.ts b/examples/example-app-v19/src/app/demo/demo-main.ts index 15f8809662..942af0017f 100644 --- a/examples/example-app-v19/src/app/demo/demo-main.ts +++ b/examples/example-app-v19/src/app/demo/demo-main.ts @@ -1,5 +1,5 @@ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { platformBrowser } from '@angular/platform-browser'; import { demoProviders } from './demo'; -platformBrowserDynamic([demoProviders]); +platformBrowser([demoProviders]); diff --git a/examples/example-app-v20/src/app/demo/demo-main.ts b/examples/example-app-v20/src/app/demo/demo-main.ts index 15f8809662..942af0017f 100644 --- a/examples/example-app-v20/src/app/demo/demo-main.ts +++ b/examples/example-app-v20/src/app/demo/demo-main.ts @@ -1,5 +1,5 @@ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { platformBrowser } from '@angular/platform-browser'; import { demoProviders } from './demo'; -platformBrowserDynamic([demoProviders]); +platformBrowser([demoProviders]); diff --git a/package.json b/package.json index df570f48bd..93f057f3b0 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "peerDependencies": { "@angular/compiler-cli": ">=18.0.0 <21.0.0", "@angular/core": ">=18.0.0 <21.0.0", + "@angular/platform-browser": ">=18.0.0 <21.0.0", "@angular/platform-browser-dynamic": ">=18.0.0 <21.0.0", "jest": "^30.0.0", "jest-environment-jsdom": "^30.0.0", diff --git a/setup-env/zone/index.js b/setup-env/zone/index.js index 31301cbf85..e8a597c625 100644 --- a/setup-env/zone/index.js +++ b/setup-env/zone/index.js @@ -1,7 +1,9 @@ require('zone.js'); require('zone.js/testing'); +const { COMPILER_OPTIONS, VERSION } = require('@angular/core'); const { getTestBed } = require('@angular/core/testing'); +const { BrowserTestingModule, platformBrowserTesting } = require('@angular/platform-browser/testing'); const { BrowserDynamicTestingModule, platformBrowserDynamicTesting, @@ -12,12 +14,25 @@ const { polyfillEncoder, resolveTestEnvOptions } = require('../utils'); const setupZoneTestEnv = (options) => { polyfillEncoder(); const testEnvironmentOptions = resolveTestEnvOptions(options); - - getTestBed().initTestEnvironment( - [BrowserDynamicTestingModule], - platformBrowserDynamicTesting(), - testEnvironmentOptions, - ); + if (+VERSION.major >= 20) { + getTestBed().initTestEnvironment( + [BrowserTestingModule], + platformBrowserTesting([ + { + provide: COMPILER_OPTIONS, + useValue: {}, + multi: true, + }, + ]), + testEnvironmentOptions, + ); + } else { + getTestBed().initTestEnvironment( + [BrowserDynamicTestingModule], + platformBrowserDynamicTesting(), + testEnvironmentOptions, + ); + } }; module.exports = { diff --git a/setup-env/zone/index.mjs b/setup-env/zone/index.mjs index 182a2e7d94..8aa1170ad8 100644 --- a/setup-env/zone/index.mjs +++ b/setup-env/zone/index.mjs @@ -1,7 +1,9 @@ import 'zone.js'; import 'zone.js/testing'; +import { COMPILER_OPTIONS, VERSION } from '@angular/core'; import { getTestBed } from '@angular/core/testing'; +import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; import { polyfillEncoder, resolveTestEnvOptions } from '../utils'; @@ -9,12 +11,25 @@ import { polyfillEncoder, resolveTestEnvOptions } from '../utils'; const setupZoneTestEnv = (options) => { polyfillEncoder(); const testEnvironmentOptions = resolveTestEnvOptions(options); - - getTestBed().initTestEnvironment( - [BrowserDynamicTestingModule], - platformBrowserDynamicTesting(), - testEnvironmentOptions, - ); + if (+VERSION.major >= 20) { + getTestBed().initTestEnvironment( + [BrowserTestingModule], + platformBrowserTesting([ + { + provide: COMPILER_OPTIONS, + useValue: {}, + multi: true, + }, + ]), + testEnvironmentOptions, + ); + } else { + getTestBed().initTestEnvironment( + [BrowserDynamicTestingModule], + platformBrowserDynamicTesting(), + testEnvironmentOptions, + ); + } }; export { setupZoneTestEnv }; diff --git a/setup-env/zoneless/index.js b/setup-env/zoneless/index.js index 5b48699b9c..965c6b240d 100644 --- a/setup-env/zoneless/index.js +++ b/setup-env/zoneless/index.js @@ -1,9 +1,10 @@ const angularCore = require('@angular/core'); -const { ErrorHandler, NgModule, VERSION } = require('@angular/core'); +const { ErrorHandler, NgModule, VERSION, COMPILER_OPTIONS } = require('@angular/core'); const { getTestBed } = require('@angular/core/testing'); +const { BrowserTestingModule, platformBrowserTesting } = require('@angular/platform-browser/testing'); const { - BrowserDynamicTestingModule, platformBrowserDynamicTesting, + BrowserDynamicTestingModule, } = require('@angular/platform-browser-dynamic/testing'); const { polyfillEncoder, resolveTestEnvOptions } = require('../utils'); @@ -32,15 +33,28 @@ const provideZonelessConfig = () => { }; const setupZonelessTestEnv = (options) => { - polyfillEncoder(); if (typeof provideZonelessChangeDetectionFn !== 'undefined') { + polyfillEncoder(); const testEnvironmentOptions = resolveTestEnvOptions(options); - - getTestBed().initTestEnvironment( - [BrowserDynamicTestingModule, provideZonelessConfig()], - platformBrowserDynamicTesting(), - testEnvironmentOptions, - ); + if (+VERSION.major >= 20) { + getTestBed().initTestEnvironment( + [BrowserTestingModule, provideZonelessConfig()], + platformBrowserTesting([ + { + provide: COMPILER_OPTIONS, + useValue: {}, + multi: true, + }, + ]), + testEnvironmentOptions, + ); + } else { + getTestBed().initTestEnvironment( + [BrowserDynamicTestingModule, provideZonelessConfig()], + platformBrowserDynamicTesting(), + testEnvironmentOptions, + ); + } return; } diff --git a/setup-env/zoneless/index.mjs b/setup-env/zoneless/index.mjs index 2b9604f8a9..0a33042578 100644 --- a/setup-env/zoneless/index.mjs +++ b/setup-env/zoneless/index.mjs @@ -1,7 +1,8 @@ import * as angularCore from '@angular/core'; -import { ErrorHandler, NgModule, VERSION } from '@angular/core'; +import { ErrorHandler, NgModule, VERSION, COMPILER_OPTIONS } from '@angular/core'; import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; +import { platformBrowserDynamicTesting, BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; import { polyfillEncoder, resolveTestEnvOptions } from '../utils'; @@ -31,15 +32,28 @@ const provideZonelessConfig = () => { }; const setupZonelessTestEnv = (options) => { - polyfillEncoder(); if (typeof provideZonelessChangeDetectionFn !== 'undefined') { + polyfillEncoder(); const testEnvironmentOptions = resolveTestEnvOptions(options); - - getTestBed().initTestEnvironment( - [BrowserDynamicTestingModule, provideZonelessConfig()], - platformBrowserDynamicTesting(), - testEnvironmentOptions, - ); + if (+VERSION.major >= 20) { + getTestBed().initTestEnvironment( + [BrowserTestingModule, provideZonelessConfig()], + platformBrowserTesting([ + { + provide: COMPILER_OPTIONS, + useValue: {}, + multi: true, + }, + ]), + testEnvironmentOptions, + ); + } else { + getTestBed().initTestEnvironment( + [BrowserDynamicTestingModule, provideZonelessConfig()], + platformBrowserDynamicTesting(), + testEnvironmentOptions, + ); + } return; } diff --git a/src/config/setup-env.spec.ts b/src/config/setup-env.spec.ts index e11a7936b1..0291824fa3 100644 --- a/src/config/setup-env.spec.ts +++ b/src/config/setup-env.spec.ts @@ -26,10 +26,18 @@ jest.mock('@angular/core/testing', () => { }; }); +class BrowserTestingModuleStub {} class BrowserDynamicTestingModuleStub {} class PlatformRefStub {} class ErrorHandlerStub {} +const mockPlatformBrowserTesting = jest.fn(() => new PlatformRefStub()); const mockPlatformBrowserDynamicTesting = jest.fn(() => new PlatformRefStub()); +jest.mock('@angular/platform-browser/testing', () => { + return { + BrowserTestingModule: new BrowserTestingModuleStub(), + platformBrowserTesting: mockPlatformBrowserTesting, + }; +}); jest.mock('@angular/platform-browser-dynamic/testing', () => { return { BrowserDynamicTestingModule: new BrowserDynamicTestingModuleStub(), @@ -44,15 +52,18 @@ jest.mock('@angular/core', () => { NgModule: () => { return jest.fn(); }, + VERSION: { + major: '20', + }, }; }); describe('Setup env utilities', () => { const assertOnInitTestEnv = (): void => { expect(mockGetTestBed).toHaveBeenCalled(); - expect(mockInitTestEnvironment.mock.calls[0][0][0]).toBeInstanceOf(BrowserDynamicTestingModuleStub); - expect(mockPlatformBrowserDynamicTesting).toHaveBeenCalled(); - expect(mockPlatformBrowserDynamicTesting.mock.results[0].value).toBeInstanceOf(PlatformRefStub); + expect(mockInitTestEnvironment.mock.calls[0][0][0]).toBeInstanceOf(BrowserTestingModuleStub); + expect(mockPlatformBrowserTesting).toHaveBeenCalled(); + expect(mockPlatformBrowserTesting.mock.results[0].value).toBeInstanceOf(PlatformRefStub); expect(mockInitTestEnvironment.mock.calls[0][2]).toEqual({ teardown: { destroyAfterEach: false, diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx index 83d818d0c5..bb9fefb6f9 100644 --- a/website/src/pages/index.tsx +++ b/website/src/pages/index.tsx @@ -3,7 +3,6 @@ import { translate } from '@docusaurus/Translate'; import useBaseUrl from '@docusaurus/useBaseUrl'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; -// eslint-disable-next-line import/no-named-as-default import clsx from 'clsx'; import React from 'react'; diff --git a/yarn.lock b/yarn.lock index 89f7e1f8f1..28734fc5aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9326,6 +9326,7 @@ __metadata: peerDependencies: "@angular/compiler-cli": ">=18.0.0 <21.0.0" "@angular/core": ">=18.0.0 <21.0.0" + "@angular/platform-browser": ">=18.0.0 <21.0.0" "@angular/platform-browser-dynamic": ">=18.0.0 <21.0.0" jest: ^30.0.0 jest-environment-jsdom: ^30.0.0 From 78380129cd883dd2c20f82e4c65d1fa9c310702f Mon Sep 17 00:00:00 2001 From: ahnpnl Date: Fri, 8 Aug 2025 20:04:33 +0200 Subject: [PATCH 2/3] docs: update copilot instructions about commit validations --- .github/copilot-instructions.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e5109289a5..8232288956 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -28,12 +28,20 @@ This repository uses modular GitHub Copilot instructions organized by topic. Ref ### Validation Before Committing -Always run the full validation suite: +- Always run code format fix: ```bash -yarn test && yarn test-esm && yarn lint && yarn lint-prettier-ci +yarn lint-fix && yarn lint-prettier ``` +- Always run the full validation suite: + +```bash +yarn test && yarn test-esm && yarn lint && yarn lint-prettier-ci && yarn test-examples +``` + +- Always run `husky` pre-commit hooks which is under `.husky` directory. + ### Key Principles - **Compatibility**: Support both CommonJS and ESM module formats From cc6e40349e505b4cdb4ef1b6a7973d1405a60c87 Mon Sep 17 00:00:00 2001 From: ahnpnl Date: Fri, 8 Aug 2025 20:33:41 +0200 Subject: [PATCH 3/3] fix: add `index.mjs` for `presets` entry point --- presets/index.d.mts | 3 +++ presets/index.mjs | 1 + 2 files changed, 4 insertions(+) create mode 100644 presets/index.d.mts create mode 100644 presets/index.mjs diff --git a/presets/index.d.mts b/presets/index.d.mts new file mode 100644 index 0000000000..e3629942fc --- /dev/null +++ b/presets/index.d.mts @@ -0,0 +1,3 @@ +import { createEsmPreset, createCjsPreset } from '../build/presets'; + +export { createEsmPreset, createCjsPreset }; diff --git a/presets/index.mjs b/presets/index.mjs new file mode 100644 index 0000000000..84f93c2dd7 --- /dev/null +++ b/presets/index.mjs @@ -0,0 +1 @@ +export * from '../build/presets';