diff --git a/.circleci/cache-version.txt b/.circleci/cache-version.txt index a57213f7e263..3080a7d0983b 100644 --- a/.circleci/cache-version.txt +++ b/.circleci/cache-version.txt @@ -1,3 +1,3 @@ # Bump this version to force CI to re-create the cache from scratch. -11-21-24 +11-26-24 diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml index e1cd082c6054..e58fa997240f 100644 --- a/.circleci/workflows.yml +++ b/.circleci/workflows.yml @@ -30,7 +30,7 @@ mainBuildFilters: &mainBuildFilters - /^release\/\d+\.\d+\.\d+$/ # use the following branch as well to ensure that v8 snapshot cache updates are fully tested - 'update-v8-snapshot-cache-on-develop' - - 'build-binary-placeholder' + - 'feat/support_angular_19' - 'publish-binary' # usually we don't build Mac app - it takes a long time @@ -42,7 +42,7 @@ macWorkflowFilters: &darwin-workflow-filters - equal: [ develop, << pipeline.git.branch >> ] # use the following branch as well to ensure that v8 snapshot cache updates are fully tested - equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ] - - equal: [ 'build-binary-placeholder', << pipeline.git.branch >> ] + - equal: [ 'feat/support_angular_19', << pipeline.git.branch >> ] - matches: pattern: /^release\/\d+\.\d+\.\d+$/ value: << pipeline.git.branch >> @@ -53,7 +53,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters - equal: [ develop, << pipeline.git.branch >> ] # use the following branch as well to ensure that v8 snapshot cache updates are fully tested - equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ] - - equal: [ 'build-binary-placeholder', << pipeline.git.branch >> ] + - equal: [ 'feat/support_angular_19', << pipeline.git.branch >> ] - matches: pattern: /^release\/\d+\.\d+\.\d+$/ value: << pipeline.git.branch >> @@ -152,7 +152,7 @@ commands: name: Set environment variable to determine whether or not to persist artifacts command: | echo "Setting SHOULD_PERSIST_ARTIFACTS variable" - echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "build-binary-placeholder" ]]; then + echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "feat/support_angular_19" ]]; then export SHOULD_PERSIST_ARTIFACTS=true fi' >> "$BASH_ENV" # You must run `setup_should_persist_artifacts` command and be using bash before running this command diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index b0921401fe31..11fc67e62c6d 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -41,6 +41,7 @@ in this [GitHub issue](https://github.com/cypress-io/cypress/issues/30447). Addr - Cypress Component Testing now supports: - `Next.js` version 15. Addresses [#30445](https://github.com/cypress-io/cypress/issues/30445). - `React` version 19. Cypress will allow detected use of the React 19 Release Candidate until React 19 is officially released. Addresses [#29470](https://github.com/cypress-io/cypress/issues/29470). + - `Angular` version 19. Addresses [#30175](https://github.com/cypress-io/cypress/issues/30175). **Bugfixes:** diff --git a/npm/angular/src/mount.ts b/npm/angular/src/mount.ts index 140b2215f248..0774d02ecc51 100644 --- a/npm/angular/src/mount.ts +++ b/npm/angular/src/mount.ts @@ -219,7 +219,9 @@ function initTestBed ( return componentFixture } -@Component({ selector: 'cy-wrapper-component', template: '' }) +// if using the Wrapper Component (template strings), the component itself cannot be +// a standalone component +@Component({ selector: 'cy-wrapper-component', template: '', standalone: false }) class WrapperComponent { } /** @@ -260,6 +262,11 @@ function setupFixture ( fixture.whenStable().then(() => { fixture.autoDetectChanges(config.autoDetectChanges ?? true) + }).catch((e) => { + // If this promise does not settle in Angular 19 it is rejected + // https://github.com/angular/angular/blob/main/CHANGELOG.md#1900-2024-11-19 + // eslint-disable-next-line no-console + console.error(e) }) return fixture diff --git a/npm/cypress-schematic/src/ct.spec.ts b/npm/cypress-schematic/src/ct.spec.ts index cea4d95625a3..5cf6ad12e7c2 100644 --- a/npm/cypress-schematic/src/ct.spec.ts +++ b/npm/cypress-schematic/src/ct.spec.ts @@ -36,7 +36,7 @@ const copyAngularMount = async (projectPath: string) => { const cypressSchematicPackagePath = path.join(__dirname, '..') -const ANGULAR_PROJECTS: ProjectFixtureDir[] = ['angular-17', 'angular-18'] +const ANGULAR_PROJECTS: ProjectFixtureDir[] = ['angular-18', 'angular-19'] describe('ng add @cypress/schematic / e2e and ct', { timeout: 1000 * 60 * 5 }, function () { for (const project of ANGULAR_PROJECTS) { diff --git a/npm/cypress-schematic/src/e2e.spec.ts b/npm/cypress-schematic/src/e2e.spec.ts index 080a9de1e6de..dad285d72ae7 100644 --- a/npm/cypress-schematic/src/e2e.spec.ts +++ b/npm/cypress-schematic/src/e2e.spec.ts @@ -25,7 +25,7 @@ const runCommandInProject = (command: string, projectPath: string) => { const cypressSchematicPackagePath = path.join(__dirname, '..') -const ANGULAR_PROJECTS: ProjectFixtureDir[] = ['angular-17', 'angular-18'] +const ANGULAR_PROJECTS: ProjectFixtureDir[] = ['angular-18', 'angular-19'] describe('ng add @cypress/schematic / only e2e', { timeout: 1000 * 60 * 5 }, function () { for (const project of ANGULAR_PROJECTS) { diff --git a/npm/webpack-dev-server/cypress/e2e/angular.cy.ts b/npm/webpack-dev-server/cypress/e2e/angular.cy.ts index e8681c7eef1d..81cd000a18db 100644 --- a/npm/webpack-dev-server/cypress/e2e/angular.cy.ts +++ b/npm/webpack-dev-server/cypress/e2e/angular.cy.ts @@ -5,6 +5,7 @@ import type { ProjectFixtureDir } from '@tooling/system-tests/lib/fixtureDirs' const WEBPACK_ANGULAR: ProjectFixtureDir[] = [ 'angular-17', 'angular-18', + 'angular-19', ] // Add to this list to focus on a particular permutation diff --git a/npm/webpack-dev-server/test/handlers/angularHandler.spec.ts b/npm/webpack-dev-server/test/handlers/angularHandler.spec.ts index d616cf0fe617..7d64f5661656 100644 --- a/npm/webpack-dev-server/test/handlers/angularHandler.spec.ts +++ b/npm/webpack-dev-server/test/handlers/angularHandler.spec.ts @@ -46,8 +46,8 @@ describe('angularHandler', function () { expectLoadsAngularBuildOptions(buildOptions) }) - it('sources the config from angular-18', async () => { - const projectRoot = await scaffoldMigrationProject('angular-18') + it('sources the config from angular-19', async () => { + const projectRoot = await scaffoldMigrationProject('angular-19') process.chdir(projectRoot) const devServerConfig = { diff --git a/packages/app/cypress/e2e/runner/reporter-ct-mount-hover.cy.ts b/packages/app/cypress/e2e/runner/reporter-ct-mount-hover.cy.ts index ab960abd43af..ded41c185eeb 100644 --- a/packages/app/cypress/e2e/runner/reporter-ct-mount-hover.cy.ts +++ b/packages/app/cypress/e2e/runner/reporter-ct-mount-hover.cy.ts @@ -3,7 +3,7 @@ import type { fixtureDirs } from '@tooling/system-tests' type ProjectDirs = typeof fixtureDirs const PROJECTS: {projectName: ProjectDirs[number], test: string}[] = [ - { projectName: 'angular-18', test: 'app.component' }, + { projectName: 'angular-19', test: 'app.component' }, { projectName: 'react-vite-ts-configured', test: 'App.cy' }, { projectName: 'react18', test: 'App.cy' }, { projectName: 'next-14', test: 'index.cy' }, diff --git a/packages/scaffold-config/src/dependencies.ts b/packages/scaffold-config/src/dependencies.ts index a5840acc96cb..59d3fdab6722 100644 --- a/packages/scaffold-config/src/dependencies.ts +++ b/packages/scaffold-config/src/dependencies.ts @@ -67,7 +67,7 @@ export const WIZARD_DEPENDENCY_ANGULAR_CLI = { package: '@angular/cli', installer: '@angular/cli', description: 'CLI tool that you use to initialize, develop, scaffold, and maintain Angular applications.', - minVersion: '^17.2.0 || ^18.0.0', + minVersion: '^17.2.0 || ^18.0.0 || ^19.0.0', } as const export const WIZARD_DEPENDENCY_ANGULAR_DEVKIT_BUILD_ANGULAR = { @@ -76,7 +76,7 @@ export const WIZARD_DEPENDENCY_ANGULAR_DEVKIT_BUILD_ANGULAR = { package: '@angular-devkit/build-angular', installer: '@angular-devkit/build-angular', description: 'Angular Webpack build facade', - minVersion: '^17.2.0 || ^18.0.0', + minVersion: '^17.2.0 || ^18.0.0 || ^19.0.0', } as const export const WIZARD_DEPENDENCY_ANGULAR_CORE = { @@ -85,7 +85,7 @@ export const WIZARD_DEPENDENCY_ANGULAR_CORE = { package: '@angular/core', installer: '@angular/core', description: 'The core of the Angular framework', - minVersion: '^17.2.0 || ^18.0.0', + minVersion: '^17.2.0 || ^18.0.0 || ^19.0.0', } as const export const WIZARD_DEPENDENCY_ANGULAR_COMMON = { @@ -94,7 +94,7 @@ export const WIZARD_DEPENDENCY_ANGULAR_COMMON = { package: '@angular/common', installer: '@angular/common', description: 'Commonly needed Angular directives and services', - minVersion: '^17.2.0 || ^18.0.0', + minVersion: '^17.2.0 || ^18.0.0 || ^19.0.0', } as const export const WIZARD_DEPENDENCY_ANGULAR_PLATFORM_BROWSER_DYNAMIC = { @@ -103,7 +103,7 @@ export const WIZARD_DEPENDENCY_ANGULAR_PLATFORM_BROWSER_DYNAMIC = { package: '@angular/platform-browser-dynamic', installer: '@angular/platform-browser-dynamic', description: 'Library for using Angular in a web browser with JIT compilation', - minVersion: '^17.2.0 || ^18.0.0', + minVersion: '^17.2.0 || ^18.0.0 || ^19.0.0', } as const export const WIZARD_DEPENDENCY_SVELTE: Cypress.CypressComponentDependency = { diff --git a/system-tests/project-fixtures/angular/src/app/app.component.ts b/system-tests/project-fixtures/angular/src/app/app.component.ts index da0ef69733da..1a40a799072a 100644 --- a/system-tests/project-fixtures/angular/src/app/app.component.ts +++ b/system-tests/project-fixtures/angular/src/app/app.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core' @Component({ selector: 'app-root', + standalone: false, templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) diff --git a/system-tests/project-fixtures/angular/src/app/components/another-child-providers.component.ts b/system-tests/project-fixtures/angular/src/app/components/another-child-providers.component.ts index 7f71862fb940..b7b8460ffc05 100644 --- a/system-tests/project-fixtures/angular/src/app/components/another-child-providers.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/another-child-providers.component.ts @@ -4,6 +4,7 @@ import { take } from 'rxjs/operators' @Component({ selector: 'app-another-child', + standalone: false, template: ``, providers: [ChildProvidersService], }) diff --git a/system-tests/project-fixtures/angular/src/app/components/button-output.component.ts b/system-tests/project-fixtures/angular/src/app/components/button-output.component.ts index 6fd90a514d4e..0aea489f596c 100644 --- a/system-tests/project-fixtures/angular/src/app/components/button-output.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/button-output.component.ts @@ -2,6 +2,7 @@ import { Component, EventEmitter, Output } from '@angular/core' @Component({ selector: 'app-button-output', + standalone: false, template: ``, }) export class ButtonOutputComponent { diff --git a/system-tests/project-fixtures/angular/src/app/components/child-providers.component.ts b/system-tests/project-fixtures/angular/src/app/components/child-providers.component.ts index f2c2e1edebe5..d9dd4e0ab291 100644 --- a/system-tests/project-fixtures/angular/src/app/components/child-providers.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/child-providers.component.ts @@ -4,6 +4,7 @@ import { take } from 'rxjs/operators' @Component({ selector: 'app-child-providers', + standalone: false, template: ``, }) export class ChildProvidersComponent { diff --git a/system-tests/project-fixtures/angular/src/app/components/child.component.ts b/system-tests/project-fixtures/angular/src/app/components/child.component.ts index 809a87df480b..302959e5adb4 100644 --- a/system-tests/project-fixtures/angular/src/app/components/child.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/child.component.ts @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core' @Component({ selector: 'child-component', + standalone: false, template: '

{{msg}}

', }) export class ChildComponent { diff --git a/system-tests/project-fixtures/angular/src/app/components/counter.component.ts b/system-tests/project-fixtures/angular/src/app/components/counter.component.ts index 35d2564f8342..04e20dee1623 100644 --- a/system-tests/project-fixtures/angular/src/app/components/counter.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/counter.component.ts @@ -3,6 +3,7 @@ import { CounterService } from './counter.service' @Component({ selector: 'counter-component', + standalone: false, template: ``, diff --git a/system-tests/project-fixtures/angular/src/app/components/lifecycle.component.ts b/system-tests/project-fixtures/angular/src/app/components/lifecycle.component.ts index 33473fb69643..7d8cfb5d9bfa 100644 --- a/system-tests/project-fixtures/angular/src/app/components/lifecycle.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/lifecycle.component.ts @@ -2,6 +2,7 @@ import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/cor @Component({ selector: 'app-lifecycle', + standalone: false, template: `

Hi {{ name }}. ngOnInit fired: {{ ngOnInitFired }} and ngOnChanges fired: {{ ngOnChangesFired }} and conditionalName: {{ conditionalName }}

`, }) export class LifecycleComponent implements OnInit, OnChanges { diff --git a/system-tests/project-fixtures/angular/src/app/components/parent-providers.component.ts b/system-tests/project-fixtures/angular/src/app/components/parent-providers.component.ts index 281c091c59bf..01fdb28367a9 100644 --- a/system-tests/project-fixtures/angular/src/app/components/parent-providers.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/parent-providers.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core' @Component({ + standalone: false, template: ` `, diff --git a/system-tests/project-fixtures/angular/src/app/components/parent.component.ts b/system-tests/project-fixtures/angular/src/app/components/parent.component.ts index a8460b6332cf..1b4d2da521b0 100644 --- a/system-tests/project-fixtures/angular/src/app/components/parent.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/parent.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core' @Component({ selector: 'parent-component', + standalone: false, template: '', }) export class ParentComponent { diff --git a/system-tests/project-fixtures/angular/src/app/components/projection.component.ts b/system-tests/project-fixtures/angular/src/app/components/projection.component.ts index 23d207165a3b..a5a66ebc9446 100644 --- a/system-tests/project-fixtures/angular/src/app/components/projection.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/projection.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core' @Component({ selector: 'app-projection', + standalone: false, template: `

`, }) export class ProjectionComponent {} diff --git a/system-tests/project-fixtures/angular/src/app/components/with-directives.component.ts b/system-tests/project-fixtures/angular/src/app/components/with-directives.component.ts index 577cbcd81a61..675effb953ad 100644 --- a/system-tests/project-fixtures/angular/src/app/components/with-directives.component.ts +++ b/system-tests/project-fixtures/angular/src/app/components/with-directives.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core' @Component({ selector: 'with-directives-component', + standalone: false, template: `