diff --git a/apps/example-app/src/app/examples/03-forms.ts b/apps/example-app/src/app/examples/03-forms.ts index f68766e4..df861a3c 100644 --- a/apps/example-app/src/app/examples/03-forms.ts +++ b/apps/example-app/src/app/examples/03-forms.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; +import { UntypedFormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-fixture', @@ -41,7 +41,7 @@ export class FormsComponent { color: ['', Validators.required], }); - constructor(private formBuilder: FormBuilder) {} + constructor(private formBuilder: UntypedFormBuilder) {} get formErrors() { return Object.keys(this.form.controls) diff --git a/apps/example-app/src/app/examples/04-forms-with-material.ts b/apps/example-app/src/app/examples/04-forms-with-material.ts index f27f4f1e..ed33dd3f 100644 --- a/apps/example-app/src/app/examples/04-forms-with-material.ts +++ b/apps/example-app/src/app/examples/04-forms-with-material.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; +import { UntypedFormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-fixture', @@ -66,7 +66,7 @@ export class MaterialFormsComponent { color: [null, Validators.required], }); - constructor(private formBuilder: FormBuilder) {} + constructor(private formBuilder: UntypedFormBuilder) {} get colorControlDisplayValue(): string | undefined { const selectedId = this.form.get('color')?.value; diff --git a/apps/example-app/src/app/examples/19-standalone-component.spec.ts b/apps/example-app/src/app/examples/19-standalone-component.spec.ts new file mode 100644 index 00000000..b21b3d7a --- /dev/null +++ b/apps/example-app/src/app/examples/19-standalone-component.spec.ts @@ -0,0 +1,22 @@ +import { render, screen } from '@testing-library/angular'; +import { StandaloneComponent, StandaloneWithChildComponent } from './19-standalone-component'; + +test('is possible to render a standalone component', async () => { + await render(StandaloneComponent); + + const content = screen.getByTestId('standalone'); + + expect(content).toHaveTextContent('Standalone Component'); +}); + +test('is possibl to render a standalone component with a child', async () => { + await render(StandaloneWithChildComponent, { + componentProperties: { name: 'Bob' }, + }); + + const childContent = screen.getByTestId('standalone'); + expect(childContent).toHaveTextContent('Standalone Component'); + + expect(screen.getByText('Hi Bob')).toBeInTheDocument(); + expect(screen.getByText('This has a child')).toBeInTheDocument(); +}); diff --git a/apps/example-app/src/app/examples/19-standalone-component.ts b/apps/example-app/src/app/examples/19-standalone-component.ts new file mode 100644 index 00000000..e203991d --- /dev/null +++ b/apps/example-app/src/app/examples/19-standalone-component.ts @@ -0,0 +1,21 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'app-standalone', + template: `
Standalone Component
`, + standalone: true, +}) +export class StandaloneComponent { } + +@Component({ + selector: 'app-standalone-with-child', + template: `

Hi {{ name }}

+

This has a child

+ `, + standalone: true, + imports: [StandaloneComponent], +}) +export class StandaloneWithChildComponent { + @Input() + name?: string; +} diff --git a/package.json b/package.json index 977d7a88..818f0dd6 100644 --- a/package.json +++ b/package.json @@ -28,16 +28,16 @@ "prepare": "git config core.hookspath .githooks" }, "dependencies": { - "@angular/animations": "13.1.1", - "@angular/cdk": "13.1.1", - "@angular/common": "13.1.1", - "@angular/compiler": "13.1.1", - "@angular/core": "13.1.1", - "@angular/material": "13.1.1", - "@angular/platform-browser": "13.1.1", - "@angular/platform-browser-dynamic": "13.1.1", - "@angular/router": "13.1.1", - "@ngrx/store": "13.0.2", + "@angular/animations": "14.0.0", + "@angular/cdk": "14.0.0", + "@angular/common": "14.0.0", + "@angular/compiler": "14.0.0", + "@angular/core": "14.0.0", + "@angular/material": "14.0.0", + "@angular/platform-browser": "14.0.0", + "@angular/platform-browser-dynamic": "14.0.0", + "@angular/router": "14.0.0", + "@ngrx/store": "14.0.0-beta.0", "@nrwl/angular": "13.4.3", "@nrwl/nx-cloud": "13.0.2", "@testing-library/dom": "^8.11.1", @@ -46,14 +46,14 @@ "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "13.1.2", + "@angular-devkit/build-angular": "14.0.0", "@angular-eslint/eslint-plugin": "13.0.1", "@angular-eslint/eslint-plugin-template": "13.0.1", "@angular-eslint/template-parser": "13.0.1", - "@angular/cli": "13.1.2", - "@angular/compiler-cli": "13.1.1", - "@angular/forms": "13.1.1", - "@angular/language-service": "13.1.1", + "@angular/cli": "14.0.0", + "@angular/compiler-cli": "14.0.0", + "@angular/forms": "14.0.0", + "@angular/language-service": "14.0.0", "@nrwl/cli": "13.4.3", "@nrwl/eslint-plugin-nx": "13.4.3", "@nrwl/jest": "13.4.3", @@ -79,14 +79,15 @@ "eslint-plugin-testing-library": "~5.0.1", "jasmine-core": "^3.10.1", "jasmine-spec-reporter": "^7.0.0", - "jest": "27.4.7", - "jest-preset-angular": "11.0.1", + "jest": "28.1.1", + "jest-environment-jsdom": "^28.1.1", + "jest-preset-angular": "12.1.0", "karma": "^6.3.9", "karma-chrome-launcher": "^3.1.0", "karma-jasmine": "^4.0.1", "karma-jasmine-html-reporter": "^1.7.0", "lint-staged": "^12.1.6", - "ng-packagr": "13.1.2", + "ng-packagr": "14.0.0", "postcss": "^8.4.5", "postcss-import": "^14.0.2", "postcss-preset-env": "^7.2.0", @@ -94,8 +95,8 @@ "prettier": "^2.4.1", "rimraf": "^3.0.2", "semantic-release": "^18.0.0", - "ts-jest": "27.1.2", + "ts-jest": "28.0.4", "ts-node": "~10.4.0", - "typescript": "4.5.4" + "typescript": "4.7.2" } } diff --git a/projects/testing-library/package.json b/projects/testing-library/package.json index 7d14c654..59ac5d28 100644 --- a/projects/testing-library/package.json +++ b/projects/testing-library/package.json @@ -29,10 +29,10 @@ "migrations": "./schematics/migrations/migration.json" }, "peerDependencies": { - "@angular/common": ">= 13.0.0", - "@angular/platform-browser": ">= 13.0.0", - "@angular/router": ">= 13.0.0", - "@angular/core": ">= 13.0.0", + "@angular/common": ">= 14.0.0", + "@angular/platform-browser": ">= 14.0.0", + "@angular/router": ">= 14.0.0", + "@angular/core": ">= 14.0.0", "rxjs": ">= 7.4.0" }, "dependencies": { diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts index baa2dce9..07fdf71d 100644 --- a/projects/testing-library/src/lib/testing-library.ts +++ b/projects/testing-library/src/lib/testing-library.ts @@ -7,6 +7,7 @@ import { OnChanges, SimpleChanges, ApplicationInitStatus, + ɵisStandalone, } from '@angular/core'; import { ComponentFixture, TestBed, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @@ -76,7 +77,7 @@ export async function render( excludeComponentDeclaration, wrapper, }), - imports: addAutoImports({ + imports: addAutoImports(sut,{ imports: imports.concat(defaultImports), routes, }), @@ -128,23 +129,23 @@ export async function render( const [path, params] = (basePath + href).split('?'); const queryParams = params ? params.split('&').reduce((qp, q) => { - const [key, value] = q.split('='); - const currentValue = qp[key]; - if (typeof currentValue === 'undefined') { - qp[key] = value; - } else if (Array.isArray(currentValue)) { - qp[key] = [...currentValue, value]; - } else { - qp[key] = [currentValue, value]; - } - return qp; - }, {} as Record) + const [key, value] = q.split('='); + const currentValue = qp[key]; + if (typeof currentValue === 'undefined') { + qp[key] = value; + } else if (Array.isArray(currentValue)) { + qp[key] = [...currentValue, value]; + } else { + qp[key] = [currentValue, value]; + } + return qp; + }, {} as Record) : undefined; const navigateOptions: NavigationExtras | undefined = queryParams ? { - queryParams, - } + queryParams, + } : undefined; const doNavigate = () => { @@ -296,11 +297,14 @@ function addAutoDeclarations( return [...declarations, wrapper]; } - const components = () => (excludeComponentDeclaration ? [] : [sut]); + const components = () => (excludeComponentDeclaration || ɵisStandalone(sut) ? [] : [sut]); return [...declarations, ...components()]; } -function addAutoImports({ imports = [], routes }: Pick, 'imports' | 'routes'>) { +function addAutoImports( + sut: Type | string, + { imports = [], routes }: Pick, 'imports' | 'routes'>, +) { const animations = () => { const animationIsDefined = imports.indexOf(NoopAnimationsModule) > -1 || imports.indexOf(BrowserAnimationsModule) > -1; @@ -308,8 +312,8 @@ function addAutoImports({ imports = [], routes }: Pick (routes ? [RouterTestingModule.withRoutes(routes)] : []); - - return [...imports, ...animations(), ...routing()]; + const components = () => (typeof sut !== 'string' && ɵisStandalone(sut) ? [sut] : []); + return [...imports, ...components(), ...animations(), ...routing()]; } /** @@ -394,7 +398,7 @@ if (typeof process === 'undefined' || !process.env?.ATL_SKIP_AUTO_CLEANUP) { } @Component({ selector: 'atl-wrapper-component', template: '' }) -class WrapperComponent {} +class WrapperComponent { } /** * Wrap findBy queries to poke the Angular change detection cycle