From b0dcf254520b22991ef030d49ca4f24d2c775c89 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 29 Nov 2024 19:52:25 +0100 Subject: [PATCH 1/2] chore: update to NX 20 (#502) --- .gitignore | 1 + .prettierignore | 3 +- jest.config.ts | 8 +++--- package.json | 73 +++++++++++++++++++++++++------------------------ 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index 215c8cb..d16a75b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ /.angular/cache .angular .nx +migrations.json .cache /.sass-cache /connect.lock diff --git a/.prettierignore b/.prettierignore index 2bdc4f9..03ff48d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -54,4 +54,5 @@ deployment.yaml .DS_Store Thumbs.db -/.nx/cache \ No newline at end of file +/.nx/cache +/.nx/workspace-data \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts index 0830aab..f5c10f4 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,5 +1,5 @@ -const { getJestProjects } = require('@nx/jest'); +const { getJestProjectsAsync } = require('@nx/jest'); -export default { - projects: getJestProjects(), -}; +export default async () => ({ + projects: await getJestProjectsAsync(), +}); diff --git a/package.json b/package.json index a934fb2..e5030d0 100644 --- a/package.json +++ b/package.json @@ -27,51 +27,52 @@ "prepare": "git config core.hookspath .githooks" }, "dependencies": { - "@angular/animations": "18.0.0", - "@angular/cdk": "18.0.0", - "@angular/common": "18.0.0", - "@angular/compiler": "18.0.0", - "@angular/core": "18.0.0", - "@angular/material": "18.0.0", - "@angular/platform-browser": "18.0.0", - "@angular/platform-browser-dynamic": "18.0.0", - "@angular/router": "18.0.0", - "@ngrx/store": "18.0.0-beta.1", - "@nx/angular": "19.1.0", + "@angular/animations": "18.2.13", + "@angular/cdk": "18.2.14", + "@angular/common": "18.2.13", + "@angular/compiler": "18.2.13", + "@angular/core": "18.2.13", + "@angular/material": "18.2.14", + "@angular/platform-browser": "18.2.13", + "@angular/platform-browser-dynamic": "18.2.13", + "@angular/router": "18.2.13", + "@ngrx/store": "18.0.2", + "@nx/angular": "20.1.3", "@testing-library/dom": "^10.0.0", "rxjs": "7.8.0", "tslib": "~2.3.1", - "zone.js": "0.14.2" + "zone.js": "0.14.10" }, "devDependencies": { - "@angular-devkit/build-angular": "18.0.1", - "@angular-devkit/core": "18.0.1", - "@angular-devkit/schematics": "18.0.1", + "@angular-devkit/build-angular": "18.2.9", + "@angular-devkit/core": "18.2.9", + "@angular-devkit/schematics": "18.2.9", "@angular-eslint/builder": "18.3.0", - "@angular-eslint/eslint-plugin": "18.3.0", - "@angular-eslint/eslint-plugin-template": "18.3.0", + "@angular-eslint/eslint-plugin": "18.0.1", + "@angular-eslint/eslint-plugin-template": "18.0.1", "@angular-eslint/schematics": "18.3.0", - "@angular-eslint/template-parser": "18.3.0", - "@angular/cli": "~18.0.0", - "@angular/compiler-cli": "18.0.0", - "@angular/forms": "18.0.0", - "@angular/language-service": "18.0.0", - "@nx/eslint": "19.1.0", - "@nx/eslint-plugin": "19.1.0", - "@nx/jest": "19.1.0", - "@nx/node": "19.1.0", - "@nx/plugin": "19.1.0", - "@nx/workspace": "19.1.0", - "@schematics/angular": "18.0.1", + "@angular-eslint/template-parser": "18.0.1", + "@angular/cli": "~18.2.0", + "@angular/compiler-cli": "18.2.13", + "@angular/forms": "18.2.13", + "@angular/language-service": "18.2.13", + "@nx/eslint": "20.1.3", + "@nx/eslint-plugin": "20.1.3", + "@nx/jest": "20.1.3", + "@nx/node": "20.1.3", + "@nx/plugin": "20.1.3", + "@nx/workspace": "20.1.3", + "@schematics/angular": "18.2.9", "@testing-library/jasmine-dom": "^1.2.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/user-event": "^14.4.3", "@types/jasmine": "4.3.1", - "@types/jest": "29.5.1", + "@types/jest": "29.5.14", "@types/node": "18.16.9", "@types/testing-library__jasmine-dom": "^1.3.0", - "@typescript-eslint/eslint-plugin": "7.3.0", - "@typescript-eslint/parser": "7.3.0", + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "^7.16.0", "autoprefixer": "^10.4.0", "cpy-cli": "^3.1.1", "eslint": "8.57.0", @@ -84,7 +85,7 @@ "jasmine-core": "4.2.0", "jasmine-spec-reporter": "7.0.0", "jest": "29.7.0", - "jest-environment-jsdom": "29.5.0", + "jest-environment-jsdom": "29.7.0", "jest-preset-angular": "14.1.0", "karma": "6.4.0", "karma-chrome-launcher": "^3.1.0", @@ -93,8 +94,8 @@ "karma-jasmine-html-reporter": "2.0.0", "lint-staged": "^12.1.6", "ng-mocks": "^14.11.0", - "ng-packagr": "18.0.0", - "nx": "19.1.0", + "ng-packagr": "18.2.1", + "nx": "20.1.3", "postcss": "^8.4.5", "postcss-import": "14.1.0", "postcss-preset-env": "7.5.0", @@ -104,6 +105,6 @@ "semantic-release": "^18.0.0", "ts-jest": "29.1.0", "ts-node": "10.9.1", - "typescript": "5.4.5" + "typescript": "5.5.4" } } From 061d5cc70aae3b2946707e1711ac833906f0aef5 Mon Sep 17 00:00:00 2001 From: Arthur Petrie Date: Sat, 30 Nov 2024 13:30:06 +0100 Subject: [PATCH 2/2] perf: optimize reduce and foreach loops (#501) --- .../src/lib/testing-library.ts | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts index ffd3898..8dfa946 100644 --- a/projects/testing-library/src/lib/testing-library.ts +++ b/projects/testing-library/src/lib/testing-library.ts @@ -2,7 +2,6 @@ import { ApplicationInitStatus, ChangeDetectorRef, Component, - isStandalone, NgZone, OnChanges, OutputRef, @@ -10,6 +9,7 @@ import { SimpleChange, SimpleChanges, Type, + isStandalone, } from '@angular/core'; import { ComponentFixture, DeferBlockBehavior, DeferBlockState, TestBed, tick } from '@angular/core/testing'; import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -27,14 +27,14 @@ import { waitForOptions as dtlWaitForOptions, within as dtlWithin, } from '@testing-library/dom'; +import { getConfig } from './config'; import { ComponentOverride, + OutputRefKeysWithCallback, RenderComponentOptions, RenderResult, RenderTemplateOptions, - OutputRefKeysWithCallback, } from './models'; -import { getConfig } from './config'; type SubscribedOutput = readonly [key: keyof T, callback: (v: any) => void, subscription: OutputRefSubscription]; @@ -71,7 +71,7 @@ export async function render( on = {}, componentProviders = [], childComponentOverrides = [], - componentImports: componentImports, + componentImports, excludeComponentDeclaration = false, routes = [], removeAngularAttributes = false, @@ -116,12 +116,9 @@ export async function render( await TestBed.compileComponents(); - componentProviders - .reduce((acc, provider) => acc.concat(provider), [] as any[]) - .forEach((p: any) => { - const { provide, ...provider } = p; - TestBed.overrideProvider(provide, provider); - }); + for (const { provide, ...provider } of componentProviders) { + TestBed.overrideProvider(provide, provider); + } const componentContainer = createComponentFixture(sut, wrapper); @@ -158,7 +155,9 @@ export async function render( let result; if (zone) { - await zone.run(() => (result = doNavigate())); + await zone.run(() => { + result = doNavigate(); + }); } else { result = doNavigate(); } @@ -199,7 +198,7 @@ export async function render( if (removeAngularAttributes) { createdFixture.nativeElement.removeAttribute('ng-version'); const idAttribute = createdFixture.nativeElement.getAttribute('id'); - if (idAttribute && idAttribute.startsWith('root')) { + if (idAttribute?.startsWith('root')) { createdFixture.nativeElement.removeAttribute('id'); } } @@ -207,7 +206,9 @@ export async function render( mountedFixtures.add(createdFixture); let isAlive = true; - createdFixture.componentRef.onDestroy(() => (isAlive = false)); + createdFixture.componentRef.onDestroy(() => { + isAlive = false; + }); if (hasOnChangesHook(createdFixture.componentInstance) && Object.keys(properties).length > 0) { const changes = getChangesObj(null, componentProperties); @@ -318,10 +319,15 @@ export async function render( }, debugElement: fixture.debugElement, container: fixture.nativeElement, - debug: (element = fixture.nativeElement, maxLength, options) => - Array.isArray(element) - ? element.forEach((e) => console.log(dtlPrettyDOM(e, maxLength, options))) - : console.log(dtlPrettyDOM(element, maxLength, options)), + debug: (element = fixture.nativeElement, maxLength, options) => { + if (Array.isArray(element)) { + for (const e of element) { + console.log(dtlPrettyDOM(e, maxLength, options)); + } + } else { + console.log(dtlPrettyDOM(element, maxLength, options)); + } + }, ...replaceFindWithFindAndDetectChanges(dtlGetQueriesForElement(fixture.nativeElement, queries)), }; } @@ -423,9 +429,11 @@ function overrideComponentImports(sut: Type | string, imports: } function overrideChildComponentProviders(componentOverrides: ComponentOverride[]) { - componentOverrides?.forEach(({ component, providers }) => { - TestBed.overrideComponent(component, { set: { providers } }); - }); + if (componentOverrides) { + for (const { component, providers } of componentOverrides) { + TestBed.overrideComponent(component, { set: { providers } }); + } + } } function hasOnChangesHook(componentInstance: SutType): componentInstance is SutType & OnChanges { @@ -439,13 +447,10 @@ function hasOnChangesHook(componentInstance: SutType): componentInstanc function getChangesObj(oldProps: Record | null, newProps: Record) { const isFirstChange = oldProps === null; - return Object.keys(newProps).reduce( - (changes, key) => ({ - ...changes, - [key]: new SimpleChange(isFirstChange ? null : oldProps[key], newProps[key], isFirstChange), - }), - {} as Record, - ); + return Object.keys(newProps).reduce((changes, key) => { + changes[key] = new SimpleChange(isFirstChange ? null : oldProps[key], newProps[key], isFirstChange); + return changes; + }, {} as Record); } function update( @@ -461,10 +466,12 @@ function update( const componentInstance = fixture.componentInstance as Record; const simpleChanges: SimpleChanges = {}; - for (const key of prevRenderedKeys) { - if (!partialUpdate && !Object.prototype.hasOwnProperty.call(newValues, key)) { - simpleChanges[key] = new SimpleChange(componentInstance[key], undefined, false); - delete componentInstance[key]; + if (!partialUpdate) { + for (const key of prevRenderedKeys) { + if (!Object.prototype.hasOwnProperty.call(newValues, key)) { + simpleChanges[key] = new SimpleChange(componentInstance[key], undefined, false); + delete componentInstance[key]; + } } } @@ -643,7 +650,7 @@ function replaceFindWithFindAndDetectChanges>(orig * Call detectChanges for all fixtures */ function detectChangesForMountedFixtures() { - mountedFixtures.forEach((fixture) => { + for (const fixture of mountedFixtures) { try { fixture.detectChanges(); } catch (err: any) { @@ -651,7 +658,7 @@ function detectChangesForMountedFixtures() { throw err; } } - }); + } } /**