From 6178330a2b5761e4735e7412b2ab8e80016d0f91 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:34:01 +0200 Subject: [PATCH 1/3] feat(schematics): migrate schematics tests to Vitest - Replace jest.config.ts with vitest.config.ts - Update project.json to use @nx/vite:test executor - Update tsconfig.spec.json: module es2022, vitest/globals types - Simplify test-setup.ts (remove jest-preset-angular zone setup) - Update nx.json production namedInputs to exclude vitest.config Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- modules/schematics/jest.config.ts | 22 - modules/schematics/project.json | 7 +- .../action/__snapshots__/index.spec.ts.snap | 58 +- modules/schematics/src/action/index.spec.ts | 3 +- .../__snapshots__/index.spec.ts.snap | 78 ++- .../src/component-store/index.spec.ts | 2 +- .../__snapshots__/index.spec.ts.snap | 151 ++++- .../schematics/src/container/index.spec.ts | 2 +- .../src/data/__snapshots__/index.spec.ts.snap | 58 +- modules/schematics/src/data/index.spec.ts | 2 +- .../effect/__snapshots__/index.spec.ts.snap | 373 ++++++++++++- modules/schematics/src/effect/index.spec.ts | 2 +- .../entity/__snapshots__/index.spec.ts.snap | 512 ++++++++++++++++- modules/schematics/src/entity/index.spec.ts | 2 +- .../feature/__snapshots__/index.spec.ts.snap | 314 ++++++++++- modules/schematics/src/feature/index.spec.ts | 2 +- modules/schematics/src/ng-add/index.spec.ts | 2 +- .../src/ngrx-push-migration/index.spec.ts | 2 +- .../reducer/__snapshots__/index.spec.ts.snap | 210 ++++++- modules/schematics/src/reducer/index.spec.ts | 2 +- .../selector/__snapshots__/index.spec.ts.snap | 105 +++- modules/schematics/src/selector/index.spec.ts | 2 +- .../store/__snapshots__/index.spec.ts.snap | 519 +++++++++++++++++- modules/schematics/src/store/index.spec.ts | 2 +- modules/schematics/test-setup.ts | 35 +- modules/schematics/tsconfig.schematics.json | 1 + modules/schematics/tsconfig.spec.json | 6 +- modules/schematics/vitest.config.mts | 26 + 28 files changed, 2443 insertions(+), 57 deletions(-) delete mode 100644 modules/schematics/jest.config.ts create mode 100644 modules/schematics/vitest.config.mts diff --git a/modules/schematics/jest.config.ts b/modules/schematics/jest.config.ts deleted file mode 100644 index 484cb41105..0000000000 --- a/modules/schematics/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'Schematics', - preset: '../../jest.preset.js', - coverageDirectory: '../../coverage/modules/schematics', - setupFilesAfterEnv: ['/test-setup.ts'], - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/modules/schematics/project.json b/modules/schematics/project.json index b8fe1b730b..a5d3fec407 100644 --- a/modules/schematics/project.json +++ b/modules/schematics/project.json @@ -17,12 +17,7 @@ "outputs": ["{options.outputFile}"] }, "test": { - "executor": "@nx/jest:jest", - "options": { - "jestConfig": "modules/schematics/jest.config.ts", - "runInBand": true, - "passWithNoTests": false - }, + "executor": "@analogjs/vitest-angular:test", "outputs": ["{workspaceRoot}/coverage/modules/schematics"] }, "build-package": { diff --git a/modules/schematics/src/action/__snapshots__/index.spec.ts.snap b/modules/schematics/src/action/__snapshots__/index.spec.ts.snap index bf4868151a..e5def0418c 100644 --- a/modules/schematics/src/action/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/action/__snapshots__/index.spec.ts.snap @@ -1,4 +1,60 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Action Schematic > api > should create api actions 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; + +export const FooActions = createActionGroup({ + source: 'Foo', + events: { + 'Load Foos': emptyProps(), + 'Load Foos Success': props<{ data: unknown }>(), + 'Load Foos Failure': props<{ error: unknown }>(), + } +}); +" +`; + +exports[`Action Schematic > should create an action with the defined prefix 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; + +export const FooActions = createActionGroup({ + source: 'Foo', + events: { + 'Prefix Foos': emptyProps(), + + + } +}); +" +`; + +exports[`Action Schematic > should create api actions (load, success, error) when the api flag is set 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; + +export const FooActions = createActionGroup({ + source: 'Foo', + events: { + 'Load Foos': emptyProps(), + 'Load Foos Success': props<{ data: unknown }>(), + 'Load Foos Failure': props<{ error: unknown }>(), + } +}); +" +`; + +exports[`Action Schematic > should define actions using createActionGroup 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; + +export const FooActions = createActionGroup({ + source: 'Foo', + events: { + 'Load Foos': emptyProps(), + + + } +}); +" +`; exports[`Action Schematic api should create api actions 1`] = ` "import { createActionGroup, emptyProps, props } from '@ngrx/store'; diff --git a/modules/schematics/src/action/index.spec.ts b/modules/schematics/src/action/index.spec.ts index 298bb1c34b..a0bce6c5a2 100644 --- a/modules/schematics/src/action/index.spec.ts +++ b/modules/schematics/src/action/index.spec.ts @@ -10,12 +10,11 @@ import { defaultWorkspaceOptions, defaultAppOptions, } from '@ngrx/schematics-core/testing'; -import { capitalize } from '../../schematics-core/utility/strings'; describe('Action Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: ActionOptions = { name: 'foo', diff --git a/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap b/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap index 2576d76bca..b44751ecb9 100644 --- a/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap @@ -1,4 +1,80 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`component-store > should import into a specified module when the module provided 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { FooStore } from './foo/foo.store'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners(), + FooStore + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`component-store > should inject the component store correctly into the spec 1`] = ` +"import { FooStore } from './foo.store'; + +describe('FooStore', () => { + const componentStore = new FooStore(); + + it('should be created', () => { + expect(componentStore).toBeTruthy(); + }); +}); +" +`; + +exports[`component-store > should not be provided into the module by default 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`component-store > should register the component store in the provided component 1`] = ` +"import { Component, signal } from '@angular/core'; +import { FooStore } from './foo/foo.store'; + +@Component({ + selector: 'app-root', + templateUrl: './app.html', + standalone: false, + styleUrl: './app.css', + providers: [FooStore] +}) +export class App { + protected readonly title = signal('bar'); +} +" +`; exports[`component-store should import into a specified module when the module provided 1`] = ` "import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; diff --git a/modules/schematics/src/component-store/index.spec.ts b/modules/schematics/src/component-store/index.spec.ts index da0339bf2d..a3d20e92f1 100644 --- a/modules/schematics/src/component-store/index.spec.ts +++ b/modules/schematics/src/component-store/index.spec.ts @@ -14,7 +14,7 @@ import { describe('component-store', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: ComponentStoreOptions = { diff --git a/modules/schematics/src/container/__snapshots__/index.spec.ts.snap b/modules/schematics/src/container/__snapshots__/index.spec.ts.snap index 4110e6b055..1f7cb14bee 100644 --- a/modules/schematics/src/container/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/container/__snapshots__/index.spec.ts.snap @@ -1,4 +1,153 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Container Schematic > display-block > should be disabled by default 1`] = `""`; + +exports[`Container Schematic > display-block > should create add style if true 1`] = ` +":host { + display: block; +} +" +`; + +exports[`Container Schematic > should import Store into the component 1`] = ` +"import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import * as fromStore from '../reducers'; + +@Component({ + selector: 'app-foo', + imports: [], + templateUrl: './foo.html', + styleUrl: './foo.css', +}) +export class Foo { + constructor(private store: Store) {} + +} +" +`; + +exports[`Container Schematic > should respect the state option if not provided 1`] = ` +"import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; + +@Component({ + selector: 'app-foo', + imports: [], + templateUrl: './foo.html', + styleUrl: './foo.css', +}) +export class Foo { + constructor(private store: Store) {} + +} +" +`; + +exports[`Container Schematic > should update the component spec 1`] = ` +"import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FooComponent } from './foo.component'; +import { provideMockStore, MockStore } from '@ngrx/store/testing'; + +describe('FooComponent', () => { + let component: FooComponent; + let fixture: ComponentFixture; + let store: MockStore; + + beforeEach(async() => { + TestBed.configureTestingModule({ + providers: [ provideMockStore() ], + declarations: [ FooComponent ] + }); + + await TestBed.compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FooComponent); + component = fixture.componentInstance; + store = TestBed.inject(Store); + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); +" +`; + +exports[`Container Schematic > should use StoreModule if integration test 1`] = ` +"import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FooComponent } from './foo.component'; +import { Store, StoreModule } from '@ngrx/store'; + +describe('FooComponent', () => { + let component: FooComponent; + let fixture: ComponentFixture; + let store: Store; + + beforeEach(async() => { + TestBed.configureTestingModule({ + imports: [ StoreModule.forRoot({}) ], + declarations: [ FooComponent ] + }); + + await TestBed.compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FooComponent); + component = fixture.componentInstance; + store = TestBed.inject(Store); + + spyOn(store, 'dispatch').and.callThrough(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); +" +`; + +exports[`Container Schematic > standalone > should be standalone by default 1`] = ` +"import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; + +@Component({ + selector: 'app-foo', + imports: [], + templateUrl: './foo.html', + styleUrl: './foo.css', +}) +export class Foo { + constructor(private store: Store) {} + +} +" +`; + +exports[`Container Schematic > standalone > should create a non-standalone component if false 1`] = ` +"import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; + +@Component({ + selector: 'app-foo', + standalone: false, + templateUrl: './foo.html', + styleUrl: './foo.css', +}) +export class Foo { + constructor(private store: Store) {} + +} +" +`; exports[`Container Schematic display-block should be disabled by default 1`] = `""`; diff --git a/modules/schematics/src/container/index.spec.ts b/modules/schematics/src/container/index.spec.ts index 4aee99cd96..3cdcb3981d 100644 --- a/modules/schematics/src/container/index.spec.ts +++ b/modules/schematics/src/container/index.spec.ts @@ -12,7 +12,7 @@ import { describe('Container Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: ContainerOptions = { diff --git a/modules/schematics/src/data/__snapshots__/index.spec.ts.snap b/modules/schematics/src/data/__snapshots__/index.spec.ts.snap index 6bf7cb4705..7ee53158a4 100644 --- a/modules/schematics/src/data/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/data/__snapshots__/index.spec.ts.snap @@ -1,4 +1,60 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Data Schematic > should create a model interface 1`] = ` +"export interface Foo { + id?: unknown; +} +" +`; + +exports[`Data Schematic > should create a service class 1`] = ` +"import { Injectable } from '@angular/core'; +import { + EntityCollectionServiceBase, + EntityCollectionServiceElementsFactory +} from '@ngrx/data'; +import { Foo } from './foo'; + +@Injectable({ providedIn: 'root' }) +export class FooService extends EntityCollectionServiceBase { + constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) { + super('Foo', serviceElementsFactory); + } +} +" +`; + +exports[`Data Schematic > should create a spec class 1`] = ` +"import { TestBed } from '@angular/core/testing'; +import { + EntityCollectionServiceElementsFactory +} from '@ngrx/data'; +import { FooService } from './foo.service'; + +describe('FooService', () => { + let service: FooService; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + providers: [ + EntityCollectionServiceElementsFactory, + FooService + ] + }); + + await TestBed.compileComponents(); + }); + + beforeEach(() => { + service = TestBed.inject(FooService); + }); + + it('should create an instance', () => { + expect(service).toBeTruthy(); + }); +}); +" +`; exports[`Data Schematic should create a model interface 1`] = ` "export interface Foo { diff --git a/modules/schematics/src/data/index.spec.ts b/modules/schematics/src/data/index.spec.ts index a96fde4334..2b29cab228 100644 --- a/modules/schematics/src/data/index.spec.ts +++ b/modules/schematics/src/data/index.spec.ts @@ -14,7 +14,7 @@ import { describe('Data Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: DataOptions = { name: 'foo', diff --git a/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap b/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap index b791781952..55de6723d0 100644 --- a/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap @@ -1,4 +1,375 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Effect Schematic > feature effects > should add an effect to the existing registered feature effects 1`] = ` +" + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import { AppComponent } from './app.component'; + import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + + @NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + EffectsModule.forRoot([RootEffects]) + EffectsModule.forFeature([UserEffects, FooEffects]) + ], + providers: [], + bootstrap: [AppComponent] + }) + export class AppModule { } + " +`; + +exports[`Effect Schematic > feature effects > should create an effect that describes a source of actions within a feature 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; + +import { concatMap } from 'rxjs/operators'; +import { Observable, EMPTY } from 'rxjs'; +import { FooActions } from './foo.actions'; + +@Injectable() +export class FooEffects { + + + loadFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.loadFoos), + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + concatMap(() => EMPTY as Observable<{ type: string }>) + ); + }); + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Effect Schematic > feature effects > should not add an effect to registered effects defined with a variable 1`] = ` +" + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import { AppComponent } from './app.component'; + import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + + @NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + EffectsModule.forRoot(effects), + EffectsModule.forFeature([FooEffects]) + ], + providers: [], + bootstrap: [AppComponent] + }) + export class AppModule { } + " +`; + +exports[`Effect Schematic > feature effects > should still register the feature effect module with an effect with the minimal flag 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + EffectsModule.forFeature([FooEffects]) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Effect Schematic > root effects > should add an effect to the empty array of registered effects 1`] = ` +" + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import { AppComponent } from './app.component'; + import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + + @NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + EffectsModule.forRoot([FooEffects]) + ], + providers: [], + bootstrap: [AppComponent] + }) + export class AppModule { } + " +`; + +exports[`Effect Schematic > root effects > should add an effect to the existing registered root effects 1`] = ` +" + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import { AppComponent } from './app.component'; + import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + + @NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + EffectsModule.forRoot([UserEffects, FooEffects]) + ], + providers: [], + bootstrap: [AppComponent] + }) + export class AppModule { } + " +`; + +exports[`Effect Schematic > root effects > should create an effect that does not define a source of actions within the root 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect } from '@ngrx/effects'; + + + +@Injectable() +export class FooEffects { + + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Effect Schematic > root effects > should register the root effect in the provided module 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + EffectsModule.forRoot([FooEffects]) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Effect Schematic > root effects > should register the root effect module without effect with the minimal flag 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { EffectsModule } from '@ngrx/effects'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + EffectsModule.forRoot([]) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Effect Schematic > should add prefix to the effect 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { catchError, map, concatMap } from 'rxjs/operators'; +import { Observable, EMPTY, of } from 'rxjs'; +import { FooActions } from './foo.actions'; + + +@Injectable() +export class FooEffects { + + customFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.customFoos), + concatMap(() => + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + EMPTY.pipe( + map(data => FooActions.customFoosSuccess({ data })), + catchError(error => of(FooActions.customFoosFailure({ error })))) + ) + ); + }); + + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Effect Schematic > should create an api effect that describes a source of actions within a feature 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { catchError, map, concatMap } from 'rxjs/operators'; +import { Observable, EMPTY, of } from 'rxjs'; +import { FooActions } from './foo.actions'; + + +@Injectable() +export class FooEffects { + + loadFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.loadFoos), + concatMap(() => + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + EMPTY.pipe( + map(data => FooActions.loadFoosSuccess({ data })), + catchError(error => of(FooActions.loadFoosFailure({ error })))) + ) + ); + }); + + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Effect Schematic > should group and nest the effect within a feature 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; + +import { concatMap } from 'rxjs/operators'; +import { Observable, EMPTY } from 'rxjs'; +import { FooActions } from '../../actions/foo/foo.actions'; + +@Injectable() +export class FooEffects { + + + loadFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.loadFoos), + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + concatMap(() => EMPTY as Observable<{ type: string }>) + ); + }); + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Effect Schematic > should import into a specified module when provided 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { EffectsModule } from '@ngrx/effects'; +import { FooEffects } from './foo/foo.effects'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + EffectsModule.forFeature([FooEffects]) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Effect Schematic > should inject the effect service correctly within the spec 1`] = ` +"import { TestBed } from '@angular/core/testing'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { Observable } from 'rxjs'; + +import { FooEffects } from './foo.effects'; + +describe('FooEffects', () => { + let actions$: Observable; + let effects: FooEffects; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + FooEffects, + provideMockActions(() => actions$) + ] + }); + + effects = TestBed.inject(FooEffects); + }); + + it('should be created', () => { + expect(effects).toBeTruthy(); + }); +}); +" +`; + +exports[`Effect Schematic > should not be provided by default 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; exports[`Effect Schematic feature effects should add an effect to the existing registered feature effects 1`] = ` " diff --git a/modules/schematics/src/effect/index.spec.ts b/modules/schematics/src/effect/index.spec.ts index 006d776623..562c2e1f69 100644 --- a/modules/schematics/src/effect/index.spec.ts +++ b/modules/schematics/src/effect/index.spec.ts @@ -15,7 +15,7 @@ import { describe('Effect Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: EffectOptions = { diff --git a/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap b/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap index 5cc8949450..4d22743c35 100644 --- a/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap @@ -1,4 +1,514 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Entity Schematic > should create 3 files 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; +import { Update } from '@ngrx/entity'; + +import { Foo } from './foo.model'; + +export const FooActions = createActionGroup({ + source: 'Foo/API', + events: { + 'Load Foos': props<{ foos: Foo[] }>(), + 'Add Foo': props<{ foo: Foo }>(), + 'Upsert Foo': props<{ foo: Foo }>(), + 'Add Foos': props<{ foos: Foo[] }>(), + 'Upsert Foos': props<{ foos: Foo[] }>(), + 'Update Foo': props<{ foo: Update }>(), + 'Update Foos': props<{ foos: Update[] }>(), + 'Delete Foo': props<{ id: string }>(), + 'Delete Foos': props<{ ids: string[] }>(), + 'Clear Foos': emptyProps(), + } +}); +" +`; + +exports[`Entity Schematic > should create 3 files 2`] = ` +"export interface Foo { + id: string; +} +" +`; + +exports[`Entity Schematic > should create 3 files 3`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; +import { Foo } from './foo.model'; +import { FooActions } from './foo.actions'; + +export const foosFeatureKey = 'foos'; + +export interface State extends EntityState { + // additional entities state properties +} + +export const adapter: EntityAdapter = createEntityAdapter(); + +export const initialState: State = adapter.getInitialState({ + // additional entity state properties +}); + +export const reducer = createReducer( + initialState, + on(FooActions.addFoo, + (state, action) => adapter.addOne(action.foo, state) + ), + on(FooActions.upsertFoo, + (state, action) => adapter.upsertOne(action.foo, state) + ), + on(FooActions.addFoos, + (state, action) => adapter.addMany(action.foos, state) + ), + on(FooActions.upsertFoos, + (state, action) => adapter.upsertMany(action.foos, state) + ), + on(FooActions.updateFoo, + (state, action) => adapter.updateOne(action.foo, state) + ), + on(FooActions.updateFoos, + (state, action) => adapter.updateMany(action.foos, state) + ), + on(FooActions.deleteFoo, + (state, action) => adapter.removeOne(action.id, state) + ), + on(FooActions.deleteFoos, + (state, action) => adapter.removeMany(action.ids, state) + ), + on(FooActions.loadFoos, + (state, action) => adapter.setAll(action.foos, state) + ), + on(FooActions.clearFoos, + state => adapter.removeAll(state) + ), +); + +export const foosFeature = createFeature({ + name: foosFeatureKey, + reducer, + extraSelectors: ({ selectFoosState }) => ({ + ...adapter.getSelectors(selectFoosState) + }), +}); + +export const { + selectIds, + selectEntities, + selectAll, + selectTotal, +} = foosFeature; +" +`; + +exports[`Entity Schematic > should create 3 files of an entity to specified project if provided 1`] = `""`; + +exports[`Entity Schematic > should create 3 files of an entity to specified project if provided 2`] = `""`; + +exports[`Entity Schematic > should create 3 files of an entity to specified project if provided 3`] = `""`; + +exports[`Entity Schematic > should create all files of an entity within grouped and nested folders 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; +import { Update } from '@ngrx/entity'; + +import { Foo } from '../../models/foo/foo.model'; + +export const FooActions = createActionGroup({ + source: 'Foo/API', + events: { + 'Load Foos': props<{ foos: Foo[] }>(), + 'Add Foo': props<{ foo: Foo }>(), + 'Upsert Foo': props<{ foo: Foo }>(), + 'Add Foos': props<{ foos: Foo[] }>(), + 'Upsert Foos': props<{ foos: Foo[] }>(), + 'Update Foo': props<{ foo: Update }>(), + 'Update Foos': props<{ foos: Update[] }>(), + 'Delete Foo': props<{ id: string }>(), + 'Delete Foos': props<{ ids: string[] }>(), + 'Clear Foos': emptyProps(), + } +}); +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped and nested folders 2`] = ` +"export interface Foo { + id: string; +} +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped and nested folders 3`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; +import { Foo } from '../../models/foo/foo.model'; +import { FooActions } from '../../actions/foo/foo.actions'; + +export const foosFeatureKey = 'foos'; + +export interface State extends EntityState { + // additional entities state properties +} + +export const adapter: EntityAdapter = createEntityAdapter(); + +export const initialState: State = adapter.getInitialState({ + // additional entity state properties +}); + +export const reducer = createReducer( + initialState, + on(FooActions.addFoo, + (state, action) => adapter.addOne(action.foo, state) + ), + on(FooActions.upsertFoo, + (state, action) => adapter.upsertOne(action.foo, state) + ), + on(FooActions.addFoos, + (state, action) => adapter.addMany(action.foos, state) + ), + on(FooActions.upsertFoos, + (state, action) => adapter.upsertMany(action.foos, state) + ), + on(FooActions.updateFoo, + (state, action) => adapter.updateOne(action.foo, state) + ), + on(FooActions.updateFoos, + (state, action) => adapter.updateMany(action.foos, state) + ), + on(FooActions.deleteFoo, + (state, action) => adapter.removeOne(action.id, state) + ), + on(FooActions.deleteFoos, + (state, action) => adapter.removeMany(action.ids, state) + ), + on(FooActions.loadFoos, + (state, action) => adapter.setAll(action.foos, state) + ), + on(FooActions.clearFoos, + state => adapter.removeAll(state) + ), +); + +export const foosFeature = createFeature({ + name: foosFeatureKey, + reducer, + extraSelectors: ({ selectFoosState }) => ({ + ...adapter.getSelectors(selectFoosState) + }), +}); + +export const { + selectIds, + selectEntities, + selectAll, + selectTotal, +} = foosFeature; +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped and nested folders 4`] = ` +"import { reducer, initialState } from '../../reducers/foo/foo.reducer'; + +describe('Foo Reducer', () => { + describe('unknown action', () => { + it('should return the previous state', () => { + const action = {} as any; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); +}); +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped folders if group is set 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; +import { Update } from '@ngrx/entity'; + +import { Foo } from '../models/foo.model'; + +export const FooActions = createActionGroup({ + source: 'Foo/API', + events: { + 'Load Foos': props<{ foos: Foo[] }>(), + 'Add Foo': props<{ foo: Foo }>(), + 'Upsert Foo': props<{ foo: Foo }>(), + 'Add Foos': props<{ foos: Foo[] }>(), + 'Upsert Foos': props<{ foos: Foo[] }>(), + 'Update Foo': props<{ foo: Update }>(), + 'Update Foos': props<{ foos: Update[] }>(), + 'Delete Foo': props<{ id: string }>(), + 'Delete Foos': props<{ ids: string[] }>(), + 'Clear Foos': emptyProps(), + } +}); +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped folders if group is set 2`] = ` +"export interface Foo { + id: string; +} +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped folders if group is set 3`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; +import { Foo } from '../models/foo.model'; +import { FooActions } from '../actions/foo.actions'; + +export const foosFeatureKey = 'foos'; + +export interface State extends EntityState { + // additional entities state properties +} + +export const adapter: EntityAdapter = createEntityAdapter(); + +export const initialState: State = adapter.getInitialState({ + // additional entity state properties +}); + +export const reducer = createReducer( + initialState, + on(FooActions.addFoo, + (state, action) => adapter.addOne(action.foo, state) + ), + on(FooActions.upsertFoo, + (state, action) => adapter.upsertOne(action.foo, state) + ), + on(FooActions.addFoos, + (state, action) => adapter.addMany(action.foos, state) + ), + on(FooActions.upsertFoos, + (state, action) => adapter.upsertMany(action.foos, state) + ), + on(FooActions.updateFoo, + (state, action) => adapter.updateOne(action.foo, state) + ), + on(FooActions.updateFoos, + (state, action) => adapter.updateMany(action.foos, state) + ), + on(FooActions.deleteFoo, + (state, action) => adapter.removeOne(action.id, state) + ), + on(FooActions.deleteFoos, + (state, action) => adapter.removeMany(action.ids, state) + ), + on(FooActions.loadFoos, + (state, action) => adapter.setAll(action.foos, state) + ), + on(FooActions.clearFoos, + state => adapter.removeAll(state) + ), +); + +export const foosFeature = createFeature({ + name: foosFeatureKey, + reducer, + extraSelectors: ({ selectFoosState }) => ({ + ...adapter.getSelectors(selectFoosState) + }), +}); + +export const { + selectIds, + selectEntities, + selectAll, + selectTotal, +} = foosFeature; +" +`; + +exports[`Entity Schematic > should create all files of an entity within grouped folders if group is set 4`] = ` +"import { reducer, initialState } from '../reducers/foo.reducer'; + +describe('Foo Reducer', () => { + describe('unknown action', () => { + it('should return the previous state', () => { + const action = {} as any; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); +}); +" +`; + +exports[`Entity Schematic > should import into a specified module 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { StoreModule } from '@ngrx/store'; +import * as fromFoo from './foo.reducer'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + StoreModule.forFeature(fromFoo.foosFeatureKey, fromFoo.reducer) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Entity Schematic > should update the state to plural 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; +import { Update } from '@ngrx/entity'; + +import { User } from './user.model'; + +export const UserActions = createActionGroup({ + source: 'User/API', + events: { + 'Load Users': props<{ users: User[] }>(), + 'Add User': props<{ user: User }>(), + 'Upsert User': props<{ user: User }>(), + 'Add Users': props<{ users: User[] }>(), + 'Upsert Users': props<{ users: User[] }>(), + 'Update User': props<{ user: Update }>(), + 'Update Users': props<{ users: Update[] }>(), + 'Delete User': props<{ id: string }>(), + 'Delete Users': props<{ ids: string[] }>(), + 'Clear Users': emptyProps(), + } +}); +" +`; + +exports[`Entity Schematic > should update the state to plural 2`] = ` +"export interface User { + id: string; +} +" +`; + +exports[`Entity Schematic > should update the state to plural 3`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; +import { User } from './user.model'; +import { UserActions } from './user.actions'; + +export const usersFeatureKey = 'users'; + +export interface State extends EntityState { + // additional entities state properties +} + +export const adapter: EntityAdapter = createEntityAdapter(); + +export const initialState: State = adapter.getInitialState({ + // additional entity state properties +}); + +export const reducer = createReducer( + initialState, + on(UserActions.addUser, + (state, action) => adapter.addOne(action.user, state) + ), + on(UserActions.upsertUser, + (state, action) => adapter.upsertOne(action.user, state) + ), + on(UserActions.addUsers, + (state, action) => adapter.addMany(action.users, state) + ), + on(UserActions.upsertUsers, + (state, action) => adapter.upsertMany(action.users, state) + ), + on(UserActions.updateUser, + (state, action) => adapter.updateOne(action.user, state) + ), + on(UserActions.updateUsers, + (state, action) => adapter.updateMany(action.users, state) + ), + on(UserActions.deleteUser, + (state, action) => adapter.removeOne(action.id, state) + ), + on(UserActions.deleteUsers, + (state, action) => adapter.removeMany(action.ids, state) + ), + on(UserActions.loadUsers, + (state, action) => adapter.setAll(action.users, state) + ), + on(UserActions.clearUsers, + state => adapter.removeAll(state) + ), +); + +export const usersFeature = createFeature({ + name: usersFeatureKey, + reducer, + extraSelectors: ({ selectUsersState }) => ({ + ...adapter.getSelectors(selectUsersState) + }), +}); + +export const { + selectIds, + selectEntities, + selectAll, + selectTotal, +} = usersFeature; +" +`; + +exports[`Entity Schematic > should update the state to plural 4`] = ` +"import { reducer, initialState } from './user.reducer'; + +describe('User Reducer', () => { + describe('unknown action', () => { + it('should return the previous state', () => { + const action = {} as any; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); +}); +" +`; + +exports[`Entity Schematic > should update the state to plural 5`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; +import * as fromUser from '../user.reducer'; + +export const userFeatureKey = 'user'; + +export interface State { + + [fromUser.usersFeatureKey]: fromUser.State; +} + +export const reducers: ActionReducerMap = { + + [fromUser.usersFeatureKey]: fromUser.reducer, +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; exports[`Entity Schematic should create 3 files 1`] = ` "import { createActionGroup, emptyProps, props } from '@ngrx/store'; diff --git a/modules/schematics/src/entity/index.spec.ts b/modules/schematics/src/entity/index.spec.ts index 79fd5df605..91942dd3ef 100644 --- a/modules/schematics/src/entity/index.spec.ts +++ b/modules/schematics/src/entity/index.spec.ts @@ -14,7 +14,7 @@ import { describe('Entity Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: EntityOptions = { name: 'foo', diff --git a/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap b/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap index ef434c06e8..a716c7f0fc 100644 --- a/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap @@ -1,4 +1,316 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Feature Schematic > should create all files of a feature with an entity 1`] = ` +"import { createActionGroup, emptyProps, props } from '@ngrx/store'; +import { Update } from '@ngrx/entity'; + +import { Foo } from './foo.model'; + +export const FooActions = createActionGroup({ + source: 'Foo/API', + events: { + 'Load Foos': props<{ foos: Foo[] }>(), + 'Add Foo': props<{ foo: Foo }>(), + 'Upsert Foo': props<{ foo: Foo }>(), + 'Add Foos': props<{ foos: Foo[] }>(), + 'Upsert Foos': props<{ foos: Foo[] }>(), + 'Update Foo': props<{ foo: Update }>(), + 'Update Foos': props<{ foos: Update[] }>(), + 'Delete Foo': props<{ id: string }>(), + 'Delete Foos': props<{ ids: string[] }>(), + 'Clear Foos': emptyProps(), + } +}); +" +`; + +exports[`Feature Schematic > should create all files of a feature with an entity 2`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; +import { Foo } from './foo.model'; +import { FooActions } from './foo.actions'; + +export const foosFeatureKey = 'foos'; + +export interface State extends EntityState { + // additional entities state properties +} + +export const adapter: EntityAdapter = createEntityAdapter(); + +export const initialState: State = adapter.getInitialState({ + // additional entity state properties +}); + +export const reducer = createReducer( + initialState, + on(FooActions.addFoo, + (state, action) => adapter.addOne(action.foo, state) + ), + on(FooActions.upsertFoo, + (state, action) => adapter.upsertOne(action.foo, state) + ), + on(FooActions.addFoos, + (state, action) => adapter.addMany(action.foos, state) + ), + on(FooActions.upsertFoos, + (state, action) => adapter.upsertMany(action.foos, state) + ), + on(FooActions.updateFoo, + (state, action) => adapter.updateOne(action.foo, state) + ), + on(FooActions.updateFoos, + (state, action) => adapter.updateMany(action.foos, state) + ), + on(FooActions.deleteFoo, + (state, action) => adapter.removeOne(action.id, state) + ), + on(FooActions.deleteFoos, + (state, action) => adapter.removeMany(action.ids, state) + ), + on(FooActions.loadFoos, + (state, action) => adapter.setAll(action.foos, state) + ), + on(FooActions.clearFoos, + state => adapter.removeAll(state) + ), +); + +export const foosFeature = createFeature({ + name: foosFeatureKey, + reducer, + extraSelectors: ({ selectFoosState }) => ({ + ...adapter.getSelectors(selectFoosState) + }), +}); + +export const { + selectIds, + selectEntities, + selectAll, + selectTotal, +} = foosFeature; +" +`; + +exports[`Feature Schematic > should create all files of a feature with an entity 3`] = ` +"import { reducer, initialState } from './foo.reducer'; + +describe('Foo Reducer', () => { + describe('unknown action', () => { + it('should return the previous state', () => { + const action = {} as any; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); +}); +" +`; + +exports[`Feature Schematic > should create all files of a feature with an entity 4`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; + +import { concatMap } from 'rxjs/operators'; +import { Observable, EMPTY } from 'rxjs'; +import { FooActions } from './foo.actions'; + +@Injectable() +export class FooEffects { + + + loadFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.loadFoos), + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + concatMap(() => EMPTY as Observable<{ type: string }>) + ); + }); + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Feature Schematic > should create all files of a feature with an entity 5`] = ` +"import { TestBed } from '@angular/core/testing'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { Observable } from 'rxjs'; + +import { FooEffects } from './foo.effects'; + +describe('FooEffects', () => { + let actions$: Observable; + let effects: FooEffects; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + FooEffects, + provideMockActions(() => actions$) + ] + }); + + effects = TestBed.inject(FooEffects); + }); + + it('should be created', () => { + expect(effects).toBeTruthy(); + }); +}); +" +`; + +exports[`Feature Schematic > should create all files of a feature with an entity 6`] = ` +"export interface Foo { + id: string; +} +" +`; + +exports[`Feature Schematic > should have all api actions in reducer if api flag enabled 1`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { FooActions } from './foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, + on(FooActions.loadFoos, state => state), + on(FooActions.loadFoosSuccess, (state, action) => state), + on(FooActions.loadFoosFailure, (state, action) => state), +); + +export const fooFeature = createFeature({ + name: fooFeatureKey, + reducer, +}); + +" +`; + +exports[`Feature Schematic > should have all api actions with prefix in reducer if api flag enabled 1`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { FooActions } from './foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, + on(FooActions.customFoos, state => state), + on(FooActions.customFoosSuccess, (state, action) => state), + on(FooActions.customFoosFailure, (state, action) => state), +); + +export const fooFeature = createFeature({ + name: fooFeatureKey, + reducer, +}); + +" +`; + +exports[`Feature Schematic > should have all api effect if api flag enabled 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { catchError, map, concatMap } from 'rxjs/operators'; +import { Observable, EMPTY, of } from 'rxjs'; +import { FooActions } from './foo.actions'; + + +@Injectable() +export class FooEffects { + + loadFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.loadFoos), + concatMap(() => + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + EMPTY.pipe( + map(data => FooActions.loadFoosSuccess({ data })), + catchError(error => of(FooActions.loadFoosFailure({ error })))) + ) + ); + }); + + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Feature Schematic > should have all api effect with prefix if api flag enabled 1`] = ` +"import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { catchError, map, concatMap } from 'rxjs/operators'; +import { Observable, EMPTY, of } from 'rxjs'; +import { FooActions } from './foo.actions'; + + +@Injectable() +export class FooEffects { + + customFoos$ = createEffect(() => { + return this.actions$.pipe( + + ofType(FooActions.customFoos), + concatMap(() => + /** An EMPTY observable only emits completion. Replace with your own observable API request */ + EMPTY.pipe( + map(data => FooActions.customFoosSuccess({ data })), + catchError(error => of(FooActions.customFoosFailure({ error })))) + ) + ); + }); + + + constructor(private actions$: Actions) {} +} +" +`; + +exports[`Feature Schematic > should respect the path provided for the feature name 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; exports[`Feature Schematic should create all files of a feature with an entity 1`] = ` "import { createActionGroup, emptyProps, props } from '@ngrx/store'; diff --git a/modules/schematics/src/feature/index.spec.ts b/modules/schematics/src/feature/index.spec.ts index d9ef18f4d4..c4ec5ff1e6 100644 --- a/modules/schematics/src/feature/index.spec.ts +++ b/modules/schematics/src/feature/index.spec.ts @@ -14,7 +14,7 @@ import { describe('Feature Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: FeatureOptions = { name: 'foo', diff --git a/modules/schematics/src/ng-add/index.spec.ts b/modules/schematics/src/ng-add/index.spec.ts index d78019bfe2..f49cbcf327 100644 --- a/modules/schematics/src/ng-add/index.spec.ts +++ b/modules/schematics/src/ng-add/index.spec.ts @@ -8,7 +8,7 @@ import { createWorkspace } from '@ngrx/schematics-core/testing'; describe('ng-add Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultWorkspace = { diff --git a/modules/schematics/src/ngrx-push-migration/index.spec.ts b/modules/schematics/src/ngrx-push-migration/index.spec.ts index 11178ce729..e170728733 100644 --- a/modules/schematics/src/ngrx-push-migration/index.spec.ts +++ b/modules/schematics/src/ngrx-push-migration/index.spec.ts @@ -8,7 +8,7 @@ import { createWorkspace } from '@ngrx/schematics-core/testing'; describe('NgrxPush migration', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); let appTree: UnitTestTree; diff --git a/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap b/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap index 700832de10..15f4576795 100644 --- a/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap @@ -1,4 +1,212 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Reducer Schematic > should create a reducer 1`] = ` +"import { createReducer, on } from '@ngrx/store'; +import { FooActions } from './foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, +); + +" +`; + +exports[`Reducer Schematic > should create a reducer with prefix in an api feature 1`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { FooActions } from './foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, + on(FooActions.customFoos, state => state), + on(FooActions.customFoosSuccess, (state, action) => state), + on(FooActions.customFoosFailure, (state, action) => state), +); + +export const fooFeature = createFeature({ + name: fooFeatureKey, + reducer, +}); + +" +`; + +exports[`Reducer Schematic > should create a reducers barrel file 1`] = ` +" + import { isDevMode } from '@angular/core'; + import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer + } from '@ngrx/store'; +import * as fromFoo from '../foo.reducer'; + + export interface State { + + [fromFoo.fooFeatureKey]: fromFoo.State; +} + + export const reducers: ActionReducerMap = { + + [fromFoo.fooFeatureKey]: fromFoo.reducer, +}; + + + export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; + " +`; + +exports[`Reducer Schematic > should create and export a reducer in a feature 1`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { FooActions } from './foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, + on(FooActions.loadFoos, state => state), + +); + +export const fooFeature = createFeature({ + name: fooFeatureKey, + reducer, +}); + +" +`; + +exports[`Reducer Schematic > should create and export a reducer in an api feature 1`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { FooActions } from './foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, + on(FooActions.loadFoos, state => state), + on(FooActions.loadFoosSuccess, (state, action) => state), + on(FooActions.loadFoosFailure, (state, action) => state), +); + +export const fooFeature = createFeature({ + name: fooFeatureKey, + reducer, +}); + +" +`; + +exports[`Reducer Schematic > should group and nest the reducer within a feature 1`] = ` +"import { createFeature, createReducer, on } from '@ngrx/store'; +import { FooActions } from '../../actions/foo/foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, + on(FooActions.loadFoos, state => state), + +); + +export const fooFeature = createFeature({ + name: fooFeatureKey, + reducer, +}); + +" +`; + +exports[`Reducer Schematic > should group within a "reducers" folder if group is set 1`] = ` +"import { createReducer, on } from '@ngrx/store'; +import { FooActions } from '../actions/foo.actions'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const initialState: State = { + +}; + +export const reducer = createReducer( + initialState, +); + +" +`; + +exports[`Reducer Schematic > should import into a specified module 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { StoreModule } from '@ngrx/store'; +import * as fromFoo from './foo.reducer'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + StoreModule.forFeature(fromFoo.fooFeatureKey, fromFoo.reducer) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; exports[`Reducer Schematic should create a reducer 1`] = ` "import { createReducer, on } from '@ngrx/store'; diff --git a/modules/schematics/src/reducer/index.spec.ts b/modules/schematics/src/reducer/index.spec.ts index 12a813107e..ad202ff1a3 100644 --- a/modules/schematics/src/reducer/index.spec.ts +++ b/modules/schematics/src/reducer/index.spec.ts @@ -15,7 +15,7 @@ import { describe('Reducer Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: ReducerOptions = { name: 'foo', diff --git a/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap b/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap index 7b41a362ae..ffc96ce7ee 100644 --- a/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap @@ -1,4 +1,107 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Selector Schematic > With feature flag > should create a selector 1`] = ` +"import { createFeatureSelector, createSelector } from '@ngrx/store'; +import * as fromFoo from './foo.reducer'; + +export const selectFooState = createFeatureSelector( + fromFoo.fooFeatureKey +); +" +`; + +exports[`Selector Schematic > With feature flag > should create a selector 2`] = ` +"import * as fromFoo from './foo.reducer'; +import { selectFooState } from './foo.selectors'; + +describe('Foo Selectors', () => { + it('should select the feature state', () => { + const result = selectFooState({ + [fromFoo.fooFeatureKey]: {} + }); + + expect(result).toEqual({}); + }); +}); +" +`; + +exports[`Selector Schematic > With feature flag > should group and nest the selectors within a feature 1`] = ` +"import { createFeatureSelector, createSelector } from '@ngrx/store'; +import * as fromFoo from '../../reducers/foo/foo.reducer'; + +export const selectFooState = createFeatureSelector( + fromFoo.fooFeatureKey +); +" +`; + +exports[`Selector Schematic > With feature flag > should group and nest the selectors within a feature 2`] = ` +"import * as fromFoo from '../../reducers/foo/foo.reducer'; +import { selectFooState } from './foo.selectors'; + +describe('Foo Selectors', () => { + it('should select the feature state', () => { + const result = selectFooState({ + [fromFoo.fooFeatureKey]: {} + }); + + expect(result).toEqual({}); + }); +}); +" +`; + +exports[`Selector Schematic > should create selector files 1`] = ` +"import { createFeatureSelector, createSelector } from '@ngrx/store'; + +" +`; + +exports[`Selector Schematic > should create selector files 2`] = ` +" + +describe('Foo Selectors', () => { + it('should select the feature state', () => { + + }); +}); +" +`; + +exports[`Selector Schematic > should group selectors if group is true 1`] = ` +"import { createFeatureSelector, createSelector } from '@ngrx/store'; + +" +`; + +exports[`Selector Schematic > should group selectors if group is true 2`] = ` +" + +describe('Foo Selectors', () => { + it('should select the feature state', () => { + + }); +}); +" +`; + +exports[`Selector Schematic > should not flatten selectors if flat is false 1`] = ` +"import { createFeatureSelector, createSelector } from '@ngrx/store'; + +" +`; + +exports[`Selector Schematic > should not flatten selectors if flat is false 2`] = ` +" + +describe('Foo Selectors', () => { + it('should select the feature state', () => { + + }); +}); +" +`; exports[`Selector Schematic With feature flag should create a selector 1`] = ` "import { createFeatureSelector, createSelector } from '@ngrx/store'; diff --git a/modules/schematics/src/selector/index.spec.ts b/modules/schematics/src/selector/index.spec.ts index 7c91150ee2..5ae6851a4f 100644 --- a/modules/schematics/src/selector/index.spec.ts +++ b/modules/schematics/src/selector/index.spec.ts @@ -12,7 +12,7 @@ import { describe('Selector Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: SelectorOptions = { name: 'foo', diff --git a/modules/schematics/src/store/__snapshots__/index.spec.ts.snap b/modules/schematics/src/store/__snapshots__/index.spec.ts.snap index db1ea0818d..541d87079a 100644 --- a/modules/schematics/src/store/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/store/__snapshots__/index.spec.ts.snap @@ -1,4 +1,521 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Store Schematic > should add a feature key if not root 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should add a feature key if not root 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should add the initial config correctly into an empty module 1`] = ` +" + import { NgModule, isDevMode } from '@angular/core'; +import { StoreModule } from '@ngrx/store'; +import { reducers, metaReducers } from './reducers'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; + + @NgModule({ + declarations: [], + imports: [StoreModule.forRoot(reducers, { metaReducers }), isDevMode() ? StoreDevtoolsModule.instrument() : []], + }) + export class EmptyModule {} + " +`; + +exports[`Store Schematic > should create the initial store setup 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should create the initial store setup 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should import a feature a specified module 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { StoreModule } from '@ngrx/store'; +import * as fromFoo from './reducers'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + StoreModule.forFeature(fromFoo.fooFeatureKey, fromFoo.reducers, { metaReducers: fromFoo.metaReducers }) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should import a feature a specified module 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should import into a specified module 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners, isDevMode } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { StoreModule } from '@ngrx/store'; +import { reducers, metaReducers } from './reducers'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + StoreModule.forRoot(reducers, { metaReducers }), + isDevMode() ? StoreDevtoolsModule.instrument() : [] + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should import into a specified module 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should not add a feature key if root 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should not add a feature key if root 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should not skip the initial store setup files if the minimal flag is provided with a feature 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { StoreModule } from '@ngrx/store'; +import * as fromFoo from './reducers'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + StoreModule.forFeature(fromFoo.fooFeatureKey, fromFoo.reducers, { metaReducers: fromFoo.metaReducers }) + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should not skip the initial store setup files if the minimal flag is provided with a feature 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + +export const fooFeatureKey = 'foo'; + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should skip the initial store setup files if the minimal flag is provided 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners, isDevMode } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; +import { StoreModule } from '@ngrx/store'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule, + StoreModule.forRoot({}), + isDevMode() ? StoreDevtoolsModule.instrument() : [] + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should support a custom feature state interface name 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should support a custom feature state interface name 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + +export const featureFeatureKey = 'feature'; + +export interface FeatureState { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should support a custom root state interface name 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should support a custom root state interface name 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + + +export interface AppState { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should support a default feature state interface name 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should support a default feature state interface name 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + +export const featureFeatureKey = 'feature'; + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; + +exports[`Store Schematic > should support a default root state interface name 1`] = ` +"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { App } from './app'; + +@NgModule({ + declarations: [ + App + ], + imports: [ + BrowserModule + ], + providers: [ + provideBrowserGlobalErrorListeners() + ], + bootstrap: [App] +}) +export class AppModule { } +" +`; + +exports[`Store Schematic > should support a default root state interface name 2`] = ` +"import { isDevMode } from '@angular/core'; +import { + ActionReducer, + ActionReducerMap, + createFeatureSelector, + createSelector, + MetaReducer +} from '@ngrx/store'; + + +export interface State { + +} + +export const reducers: ActionReducerMap = { + +}; + + +export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; +" +`; exports[`Store Schematic should add a feature key if not root 1`] = ` "import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; diff --git a/modules/schematics/src/store/index.spec.ts b/modules/schematics/src/store/index.spec.ts index f221b405a1..d65bd56d67 100644 --- a/modules/schematics/src/store/index.spec.ts +++ b/modules/schematics/src/store/index.spec.ts @@ -14,7 +14,7 @@ import { describe('Store Schematic', () => { const schematicRunner = new SchematicTestRunner( '@ngrx/schematics', - path.join(__dirname, '../../collection.json') + path.join(process.cwd(), 'dist/modules/schematics/collection.json') ); const defaultOptions: StoreOptions = { name: 'foo', diff --git a/modules/schematics/test-setup.ts b/modules/schematics/test-setup.ts index 04187448f9..3512059d4b 100644 --- a/modules/schematics/test-setup.ts +++ b/modules/schematics/test-setup.ts @@ -1,4 +1,33 @@ -import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; +import { + TextEncoder as NodeTextEncoder, + TextDecoder as NodeTextDecoder, +} from 'util'; -setupZoneTestEnv(); -Object.assign(global, { TextDecoder, TextEncoder }); +// Only assign if not already defined, using type assertion to satisfy TypeScript +if (typeof globalThis.TextEncoder === 'undefined') { + globalThis.TextEncoder = NodeTextEncoder as unknown as { + new (): TextEncoder; + prototype: TextEncoder; + }; +} + +if (typeof globalThis.TextDecoder === 'undefined') { + globalThis.TextDecoder = NodeTextDecoder as unknown as { + new (): TextDecoder; + prototype: TextDecoder; + }; +} + +import '@angular/compiler'; +import '@analogjs/vitest-angular/setup-zone'; + +import { + BrowserTestingModule, + platformBrowserTesting, +} from '@angular/platform-browser/testing'; +import { getTestBed } from '@angular/core/testing'; + +getTestBed().initTestEnvironment( + BrowserTestingModule, + platformBrowserTesting() +); diff --git a/modules/schematics/tsconfig.schematics.json b/modules/schematics/tsconfig.schematics.json index bf10406f79..324de466f4 100644 --- a/modules/schematics/tsconfig.schematics.json +++ b/modules/schematics/tsconfig.schematics.json @@ -5,6 +5,7 @@ "stripInternal": true, "experimentalDecorators": true, "module": "nodenext", + "target": "es2022", "moduleResolution": "nodenext", "downlevelIteration": true, "outDir": "../../dist/modules/schematics", diff --git a/modules/schematics/tsconfig.spec.json b/modules/schematics/tsconfig.spec.json index dcb4681eef..707b7d198b 100644 --- a/modules/schematics/tsconfig.spec.json +++ b/modules/schematics/tsconfig.spec.json @@ -2,10 +2,10 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], + "module": "es2022", + "types": ["vitest/globals", "node"], "target": "es2016" }, "files": ["test-setup.ts"], - "include": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts", "**/*.d.ts"] + "include": ["vitest.config.ts", "**/*.spec.ts", "**/*.test.ts", "**/*.d.ts"] } diff --git a/modules/schematics/vitest.config.mts b/modules/schematics/vitest.config.mts new file mode 100644 index 0000000000..8efa608bcf --- /dev/null +++ b/modules/schematics/vitest.config.mts @@ -0,0 +1,26 @@ +/// + +import angular from '@analogjs/vite-plugin-angular'; + +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config/ +export default defineConfig(({ mode }) => { + return { + root: __dirname, + plugins: [angular(), nxViteTsPaths()], + test: { + globals: true, + pool: 'forks', + environment: 'jsdom', + setupFiles: ['test-setup.ts'], + include: ['src/**/*.spec.ts'], + reporters: ['default'], + }, + define: { + 'import.meta.vitest': mode !== 'production', + }, + }; +}); From add43c15efbb01c07a526547b20cd5442bebf373 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:09:33 +0200 Subject: [PATCH 2/3] build(schematics): build package before testing --- modules/schematics/project.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/schematics/project.json b/modules/schematics/project.json index a5d3fec407..671649ed3d 100644 --- a/modules/schematics/project.json +++ b/modules/schematics/project.json @@ -16,10 +16,6 @@ }, "outputs": ["{options.outputFile}"] }, - "test": { - "executor": "@analogjs/vitest-angular:test", - "outputs": ["{workspaceRoot}/coverage/modules/schematics"] - }, "build-package": { "executor": "@nx/js:tsc", "options": { @@ -78,6 +74,11 @@ ] }, "outputs": ["{workspaceRoot}/dist/modules/schematics"] + }, + "test": { + "executor": "@analogjs/vitest-angular:test", + "dependsOn": ["build"], + "outputs": ["{workspaceRoot}/coverage/modules/schematics"] } } } From 15eb9ef8f92d608e0688cb0d4d5007a7bc3d4629 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:37:23 +0200 Subject: [PATCH 3/3] update snapshot linebreaks --- .../action/__snapshots__/index.spec.ts.snap | 56 -- .../__snapshots__/index.spec.ts.snap | 76 --- .../__snapshots__/index.spec.ts.snap | 149 ----- .../src/data/__snapshots__/index.spec.ts.snap | 56 -- .../effect/__snapshots__/index.spec.ts.snap | 371 ------------- .../entity/__snapshots__/index.spec.ts.snap | 510 ----------------- .../feature/__snapshots__/index.spec.ts.snap | 312 ----------- .../reducer/__snapshots__/index.spec.ts.snap | 208 ------- .../selector/__snapshots__/index.spec.ts.snap | 103 ---- .../store/__snapshots__/index.spec.ts.snap | 517 ------------------ 10 files changed, 2358 deletions(-) diff --git a/modules/schematics/src/action/__snapshots__/index.spec.ts.snap b/modules/schematics/src/action/__snapshots__/index.spec.ts.snap index e5def0418c..990f26de60 100644 --- a/modules/schematics/src/action/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/action/__snapshots__/index.spec.ts.snap @@ -55,59 +55,3 @@ export const FooActions = createActionGroup({ }); " `; - -exports[`Action Schematic api should create api actions 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; - -export const FooActions = createActionGroup({ - source: 'Foo', - events: { - 'Load Foos': emptyProps(), - 'Load Foos Success': props<{ data: unknown }>(), - 'Load Foos Failure': props<{ error: unknown }>(), - } -}); -" -`; - -exports[`Action Schematic should create an action with the defined prefix 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; - -export const FooActions = createActionGroup({ - source: 'Foo', - events: { - 'Prefix Foos': emptyProps(), - - - } -}); -" -`; - -exports[`Action Schematic should create api actions (load, success, error) when the api flag is set 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; - -export const FooActions = createActionGroup({ - source: 'Foo', - events: { - 'Load Foos': emptyProps(), - 'Load Foos Success': props<{ data: unknown }>(), - 'Load Foos Failure': props<{ error: unknown }>(), - } -}); -" -`; - -exports[`Action Schematic should define actions using createActionGroup 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; - -export const FooActions = createActionGroup({ - source: 'Foo', - events: { - 'Load Foos': emptyProps(), - - - } -}); -" -`; diff --git a/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap b/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap index b44751ecb9..c002b30e03 100644 --- a/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/component-store/__snapshots__/index.spec.ts.snap @@ -75,79 +75,3 @@ export class App { } " `; - -exports[`component-store should import into a specified module when the module provided 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { FooStore } from './foo/foo.store'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners(), - FooStore - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`component-store should inject the component store correctly into the spec 1`] = ` -"import { FooStore } from './foo.store'; - -describe('FooStore', () => { - const componentStore = new FooStore(); - - it('should be created', () => { - expect(componentStore).toBeTruthy(); - }); -}); -" -`; - -exports[`component-store should not be provided into the module by default 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`component-store should register the component store in the provided component 1`] = ` -"import { Component, signal } from '@angular/core'; -import { FooStore } from './foo/foo.store'; - -@Component({ - selector: 'app-root', - templateUrl: './app.html', - standalone: false, - styleUrl: './app.css', - providers: [FooStore] -}) -export class App { - protected readonly title = signal('bar'); -} -" -`; diff --git a/modules/schematics/src/container/__snapshots__/index.spec.ts.snap b/modules/schematics/src/container/__snapshots__/index.spec.ts.snap index 1f7cb14bee..12b48304e0 100644 --- a/modules/schematics/src/container/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/container/__snapshots__/index.spec.ts.snap @@ -22,7 +22,6 @@ import * as fromStore from '../reducers'; }) export class Foo { constructor(private store: Store) {} - } " `; @@ -39,7 +38,6 @@ import { Store } from '@ngrx/store'; }) export class Foo { constructor(private store: Store) {} - } " `; @@ -127,7 +125,6 @@ import { Store } from '@ngrx/store'; }) export class Foo { constructor(private store: Store) {} - } " `; @@ -136,152 +133,6 @@ exports[`Container Schematic > standalone > should create a non-standalone compo "import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; -@Component({ - selector: 'app-foo', - standalone: false, - templateUrl: './foo.html', - styleUrl: './foo.css', -}) -export class Foo { - constructor(private store: Store) {} - -} -" -`; - -exports[`Container Schematic display-block should be disabled by default 1`] = `""`; - -exports[`Container Schematic display-block should create add style if true 1`] = ` -":host { - display: block; -} -" -`; - -exports[`Container Schematic should import Store into the component 1`] = ` -"import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; -import * as fromStore from '../reducers'; - -@Component({ - selector: 'app-foo', - imports: [], - templateUrl: './foo.html', - styleUrl: './foo.css', -}) -export class Foo { - constructor(private store: Store) {} -} -" -`; - -exports[`Container Schematic should respect the state option if not provided 1`] = ` -"import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; - -@Component({ - selector: 'app-foo', - imports: [], - templateUrl: './foo.html', - styleUrl: './foo.css', -}) -export class Foo { - constructor(private store: Store) {} -} -" -`; - -exports[`Container Schematic should update the component spec 1`] = ` -"import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FooComponent } from './foo.component'; -import { provideMockStore, MockStore } from '@ngrx/store/testing'; - -describe('FooComponent', () => { - let component: FooComponent; - let fixture: ComponentFixture; - let store: MockStore; - - beforeEach(async() => { - TestBed.configureTestingModule({ - providers: [ provideMockStore() ], - declarations: [ FooComponent ] - }); - - await TestBed.compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(FooComponent); - component = fixture.componentInstance; - store = TestBed.inject(Store); - - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); -" -`; - -exports[`Container Schematic should use StoreModule if integration test 1`] = ` -"import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FooComponent } from './foo.component'; -import { Store, StoreModule } from '@ngrx/store'; - -describe('FooComponent', () => { - let component: FooComponent; - let fixture: ComponentFixture; - let store: Store; - - beforeEach(async() => { - TestBed.configureTestingModule({ - imports: [ StoreModule.forRoot({}) ], - declarations: [ FooComponent ] - }); - - await TestBed.compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(FooComponent); - component = fixture.componentInstance; - store = TestBed.inject(Store); - - spyOn(store, 'dispatch').and.callThrough(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); -" -`; - -exports[`Container Schematic standalone should be standalone by default 1`] = ` -"import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; - -@Component({ - selector: 'app-foo', - imports: [], - templateUrl: './foo.html', - styleUrl: './foo.css', -}) -export class Foo { - constructor(private store: Store) {} -} -" -`; - -exports[`Container Schematic standalone should create a non-standalone component if false 1`] = ` -"import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; - @Component({ selector: 'app-foo', standalone: false, diff --git a/modules/schematics/src/data/__snapshots__/index.spec.ts.snap b/modules/schematics/src/data/__snapshots__/index.spec.ts.snap index 7ee53158a4..325fa69187 100644 --- a/modules/schematics/src/data/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/data/__snapshots__/index.spec.ts.snap @@ -55,59 +55,3 @@ describe('FooService', () => { }); " `; - -exports[`Data Schematic should create a model interface 1`] = ` -"export interface Foo { - id?: unknown; -} -" -`; - -exports[`Data Schematic should create a service class 1`] = ` -"import { Injectable } from '@angular/core'; -import { - EntityCollectionServiceBase, - EntityCollectionServiceElementsFactory -} from '@ngrx/data'; -import { Foo } from './foo'; - -@Injectable({ providedIn: 'root' }) -export class FooService extends EntityCollectionServiceBase { - constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) { - super('Foo', serviceElementsFactory); - } -} -" -`; - -exports[`Data Schematic should create a spec class 1`] = ` -"import { TestBed } from '@angular/core/testing'; -import { - EntityCollectionServiceElementsFactory -} from '@ngrx/data'; -import { FooService } from './foo.service'; - -describe('FooService', () => { - let service: FooService; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - providers: [ - EntityCollectionServiceElementsFactory, - FooService - ] - }); - - await TestBed.compileComponents(); - }); - - beforeEach(() => { - service = TestBed.inject(FooService); - }); - - it('should create an instance', () => { - expect(service).toBeTruthy(); - }); -}); -" -`; diff --git a/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap b/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap index 55de6723d0..b089de176f 100644 --- a/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/effect/__snapshots__/index.spec.ts.snap @@ -370,374 +370,3 @@ import { App } from './app'; export class AppModule { } " `; - -exports[`Effect Schematic feature effects should add an effect to the existing registered feature effects 1`] = ` -" - import { BrowserModule } from '@angular/platform-browser'; - import { NgModule } from '@angular/core'; - import { AppComponent } from './app.component'; - import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - - @NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule, - EffectsModule.forRoot([RootEffects]) - EffectsModule.forFeature([UserEffects, FooEffects]) - ], - providers: [], - bootstrap: [AppComponent] - }) - export class AppModule { } - " -`; - -exports[`Effect Schematic feature effects should create an effect that describes a source of actions within a feature 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; - -import { concatMap } from 'rxjs/operators'; -import { Observable, EMPTY } from 'rxjs'; -import { FooActions } from './foo.actions'; - -@Injectable() -export class FooEffects { - - - loadFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.loadFoos), - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - concatMap(() => EMPTY as Observable<{ type: string }>) - ); - }); - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Effect Schematic feature effects should not add an effect to registered effects defined with a variable 1`] = ` -" - import { BrowserModule } from '@angular/platform-browser'; - import { NgModule } from '@angular/core'; - import { AppComponent } from './app.component'; - import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - - @NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule, - EffectsModule.forRoot(effects), - EffectsModule.forFeature([FooEffects]) - ], - providers: [], - bootstrap: [AppComponent] - }) - export class AppModule { } - " -`; - -exports[`Effect Schematic feature effects should still register the feature effect module with an effect with the minimal flag 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - EffectsModule.forFeature([FooEffects]) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Effect Schematic root effects should add an effect to the empty array of registered effects 1`] = ` -" - import { BrowserModule } from '@angular/platform-browser'; - import { NgModule } from '@angular/core'; - import { AppComponent } from './app.component'; - import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - - @NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule, - EffectsModule.forRoot([FooEffects]) - ], - providers: [], - bootstrap: [AppComponent] - }) - export class AppModule { } - " -`; - -exports[`Effect Schematic root effects should add an effect to the existing registered root effects 1`] = ` -" - import { BrowserModule } from '@angular/platform-browser'; - import { NgModule } from '@angular/core'; - import { AppComponent } from './app.component'; - import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - - @NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule, - EffectsModule.forRoot([UserEffects, FooEffects]) - ], - providers: [], - bootstrap: [AppComponent] - }) - export class AppModule { } - " -`; - -exports[`Effect Schematic root effects should create an effect that does not define a source of actions within the root 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect } from '@ngrx/effects'; - - - -@Injectable() -export class FooEffects { - - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Effect Schematic root effects should register the root effect in the provided module 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - EffectsModule.forRoot([FooEffects]) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Effect Schematic root effects should register the root effect module without effect with the minimal flag 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { EffectsModule } from '@ngrx/effects'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - EffectsModule.forRoot([]) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Effect Schematic should add prefix to the effect 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { catchError, map, concatMap } from 'rxjs/operators'; -import { Observable, EMPTY, of } from 'rxjs'; -import { FooActions } from './foo.actions'; - - -@Injectable() -export class FooEffects { - - customFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.customFoos), - concatMap(() => - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - EMPTY.pipe( - map(data => FooActions.customFoosSuccess({ data })), - catchError(error => of(FooActions.customFoosFailure({ error })))) - ) - ); - }); - - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Effect Schematic should create an api effect that describes a source of actions within a feature 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { catchError, map, concatMap } from 'rxjs/operators'; -import { Observable, EMPTY, of } from 'rxjs'; -import { FooActions } from './foo.actions'; - - -@Injectable() -export class FooEffects { - - loadFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.loadFoos), - concatMap(() => - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - EMPTY.pipe( - map(data => FooActions.loadFoosSuccess({ data })), - catchError(error => of(FooActions.loadFoosFailure({ error })))) - ) - ); - }); - - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Effect Schematic should group and nest the effect within a feature 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; - -import { concatMap } from 'rxjs/operators'; -import { Observable, EMPTY } from 'rxjs'; -import { FooActions } from '../../actions/foo/foo.actions'; - -@Injectable() -export class FooEffects { - - - loadFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.loadFoos), - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - concatMap(() => EMPTY as Observable<{ type: string }>) - ); - }); - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Effect Schematic should import into a specified module when provided 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { EffectsModule } from '@ngrx/effects'; -import { FooEffects } from './foo/foo.effects'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - EffectsModule.forFeature([FooEffects]) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Effect Schematic should inject the effect service correctly within the spec 1`] = ` -"import { TestBed } from '@angular/core/testing'; -import { provideMockActions } from '@ngrx/effects/testing'; -import { Observable } from 'rxjs'; - -import { FooEffects } from './foo.effects'; - -describe('FooEffects', () => { - let actions$: Observable; - let effects: FooEffects; - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - FooEffects, - provideMockActions(() => actions$) - ] - }); - - effects = TestBed.inject(FooEffects); - }); - - it('should be created', () => { - expect(effects).toBeTruthy(); - }); -}); -" -`; - -exports[`Effect Schematic should not be provided by default 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; diff --git a/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap b/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap index 4d22743c35..a6ab3f5dd8 100644 --- a/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/entity/__snapshots__/index.spec.ts.snap @@ -506,516 +506,6 @@ export const reducers: ActionReducerMap = { }; -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Entity Schematic should create 3 files 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; -import { Update } from '@ngrx/entity'; - -import { Foo } from './foo.model'; - -export const FooActions = createActionGroup({ - source: 'Foo/API', - events: { - 'Load Foos': props<{ foos: Foo[] }>(), - 'Add Foo': props<{ foo: Foo }>(), - 'Upsert Foo': props<{ foo: Foo }>(), - 'Add Foos': props<{ foos: Foo[] }>(), - 'Upsert Foos': props<{ foos: Foo[] }>(), - 'Update Foo': props<{ foo: Update }>(), - 'Update Foos': props<{ foos: Update[] }>(), - 'Delete Foo': props<{ id: string }>(), - 'Delete Foos': props<{ ids: string[] }>(), - 'Clear Foos': emptyProps(), - } -}); -" -`; - -exports[`Entity Schematic should create 3 files 2`] = ` -"export interface Foo { - id: string; -} -" -`; - -exports[`Entity Schematic should create 3 files 3`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; -import { Foo } from './foo.model'; -import { FooActions } from './foo.actions'; - -export const foosFeatureKey = 'foos'; - -export interface State extends EntityState { - // additional entities state properties -} - -export const adapter: EntityAdapter = createEntityAdapter(); - -export const initialState: State = adapter.getInitialState({ - // additional entity state properties -}); - -export const reducer = createReducer( - initialState, - on(FooActions.addFoo, - (state, action) => adapter.addOne(action.foo, state) - ), - on(FooActions.upsertFoo, - (state, action) => adapter.upsertOne(action.foo, state) - ), - on(FooActions.addFoos, - (state, action) => adapter.addMany(action.foos, state) - ), - on(FooActions.upsertFoos, - (state, action) => adapter.upsertMany(action.foos, state) - ), - on(FooActions.updateFoo, - (state, action) => adapter.updateOne(action.foo, state) - ), - on(FooActions.updateFoos, - (state, action) => adapter.updateMany(action.foos, state) - ), - on(FooActions.deleteFoo, - (state, action) => adapter.removeOne(action.id, state) - ), - on(FooActions.deleteFoos, - (state, action) => adapter.removeMany(action.ids, state) - ), - on(FooActions.loadFoos, - (state, action) => adapter.setAll(action.foos, state) - ), - on(FooActions.clearFoos, - state => adapter.removeAll(state) - ), -); - -export const foosFeature = createFeature({ - name: foosFeatureKey, - reducer, - extraSelectors: ({ selectFoosState }) => ({ - ...adapter.getSelectors(selectFoosState) - }), -}); - -export const { - selectIds, - selectEntities, - selectAll, - selectTotal, -} = foosFeature; -" -`; - -exports[`Entity Schematic should create 3 files of an entity to specified project if provided 1`] = `""`; - -exports[`Entity Schematic should create 3 files of an entity to specified project if provided 2`] = `""`; - -exports[`Entity Schematic should create 3 files of an entity to specified project if provided 3`] = `""`; - -exports[`Entity Schematic should create all files of an entity within grouped and nested folders 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; -import { Update } from '@ngrx/entity'; - -import { Foo } from '../../models/foo/foo.model'; - -export const FooActions = createActionGroup({ - source: 'Foo/API', - events: { - 'Load Foos': props<{ foos: Foo[] }>(), - 'Add Foo': props<{ foo: Foo }>(), - 'Upsert Foo': props<{ foo: Foo }>(), - 'Add Foos': props<{ foos: Foo[] }>(), - 'Upsert Foos': props<{ foos: Foo[] }>(), - 'Update Foo': props<{ foo: Update }>(), - 'Update Foos': props<{ foos: Update[] }>(), - 'Delete Foo': props<{ id: string }>(), - 'Delete Foos': props<{ ids: string[] }>(), - 'Clear Foos': emptyProps(), - } -}); -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped and nested folders 2`] = ` -"export interface Foo { - id: string; -} -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped and nested folders 3`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; -import { Foo } from '../../models/foo/foo.model'; -import { FooActions } from '../../actions/foo/foo.actions'; - -export const foosFeatureKey = 'foos'; - -export interface State extends EntityState { - // additional entities state properties -} - -export const adapter: EntityAdapter = createEntityAdapter(); - -export const initialState: State = adapter.getInitialState({ - // additional entity state properties -}); - -export const reducer = createReducer( - initialState, - on(FooActions.addFoo, - (state, action) => adapter.addOne(action.foo, state) - ), - on(FooActions.upsertFoo, - (state, action) => adapter.upsertOne(action.foo, state) - ), - on(FooActions.addFoos, - (state, action) => adapter.addMany(action.foos, state) - ), - on(FooActions.upsertFoos, - (state, action) => adapter.upsertMany(action.foos, state) - ), - on(FooActions.updateFoo, - (state, action) => adapter.updateOne(action.foo, state) - ), - on(FooActions.updateFoos, - (state, action) => adapter.updateMany(action.foos, state) - ), - on(FooActions.deleteFoo, - (state, action) => adapter.removeOne(action.id, state) - ), - on(FooActions.deleteFoos, - (state, action) => adapter.removeMany(action.ids, state) - ), - on(FooActions.loadFoos, - (state, action) => adapter.setAll(action.foos, state) - ), - on(FooActions.clearFoos, - state => adapter.removeAll(state) - ), -); - -export const foosFeature = createFeature({ - name: foosFeatureKey, - reducer, - extraSelectors: ({ selectFoosState }) => ({ - ...adapter.getSelectors(selectFoosState) - }), -}); - -export const { - selectIds, - selectEntities, - selectAll, - selectTotal, -} = foosFeature; -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped and nested folders 4`] = ` -"import { reducer, initialState } from '../../reducers/foo/foo.reducer'; - -describe('Foo Reducer', () => { - describe('unknown action', () => { - it('should return the previous state', () => { - const action = {} as any; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }); - }); -}); -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped folders if group is set 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; -import { Update } from '@ngrx/entity'; - -import { Foo } from '../models/foo.model'; - -export const FooActions = createActionGroup({ - source: 'Foo/API', - events: { - 'Load Foos': props<{ foos: Foo[] }>(), - 'Add Foo': props<{ foo: Foo }>(), - 'Upsert Foo': props<{ foo: Foo }>(), - 'Add Foos': props<{ foos: Foo[] }>(), - 'Upsert Foos': props<{ foos: Foo[] }>(), - 'Update Foo': props<{ foo: Update }>(), - 'Update Foos': props<{ foos: Update[] }>(), - 'Delete Foo': props<{ id: string }>(), - 'Delete Foos': props<{ ids: string[] }>(), - 'Clear Foos': emptyProps(), - } -}); -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped folders if group is set 2`] = ` -"export interface Foo { - id: string; -} -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped folders if group is set 3`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; -import { Foo } from '../models/foo.model'; -import { FooActions } from '../actions/foo.actions'; - -export const foosFeatureKey = 'foos'; - -export interface State extends EntityState { - // additional entities state properties -} - -export const adapter: EntityAdapter = createEntityAdapter(); - -export const initialState: State = adapter.getInitialState({ - // additional entity state properties -}); - -export const reducer = createReducer( - initialState, - on(FooActions.addFoo, - (state, action) => adapter.addOne(action.foo, state) - ), - on(FooActions.upsertFoo, - (state, action) => adapter.upsertOne(action.foo, state) - ), - on(FooActions.addFoos, - (state, action) => adapter.addMany(action.foos, state) - ), - on(FooActions.upsertFoos, - (state, action) => adapter.upsertMany(action.foos, state) - ), - on(FooActions.updateFoo, - (state, action) => adapter.updateOne(action.foo, state) - ), - on(FooActions.updateFoos, - (state, action) => adapter.updateMany(action.foos, state) - ), - on(FooActions.deleteFoo, - (state, action) => adapter.removeOne(action.id, state) - ), - on(FooActions.deleteFoos, - (state, action) => adapter.removeMany(action.ids, state) - ), - on(FooActions.loadFoos, - (state, action) => adapter.setAll(action.foos, state) - ), - on(FooActions.clearFoos, - state => adapter.removeAll(state) - ), -); - -export const foosFeature = createFeature({ - name: foosFeatureKey, - reducer, - extraSelectors: ({ selectFoosState }) => ({ - ...adapter.getSelectors(selectFoosState) - }), -}); - -export const { - selectIds, - selectEntities, - selectAll, - selectTotal, -} = foosFeature; -" -`; - -exports[`Entity Schematic should create all files of an entity within grouped folders if group is set 4`] = ` -"import { reducer, initialState } from '../reducers/foo.reducer'; - -describe('Foo Reducer', () => { - describe('unknown action', () => { - it('should return the previous state', () => { - const action = {} as any; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }); - }); -}); -" -`; - -exports[`Entity Schematic should import into a specified module 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { StoreModule } from '@ngrx/store'; -import * as fromFoo from './foo.reducer'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - StoreModule.forFeature(fromFoo.foosFeatureKey, fromFoo.reducer) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Entity Schematic should update the state to plural 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; -import { Update } from '@ngrx/entity'; - -import { User } from './user.model'; - -export const UserActions = createActionGroup({ - source: 'User/API', - events: { - 'Load Users': props<{ users: User[] }>(), - 'Add User': props<{ user: User }>(), - 'Upsert User': props<{ user: User }>(), - 'Add Users': props<{ users: User[] }>(), - 'Upsert Users': props<{ users: User[] }>(), - 'Update User': props<{ user: Update }>(), - 'Update Users': props<{ users: Update[] }>(), - 'Delete User': props<{ id: string }>(), - 'Delete Users': props<{ ids: string[] }>(), - 'Clear Users': emptyProps(), - } -}); -" -`; - -exports[`Entity Schematic should update the state to plural 2`] = ` -"export interface User { - id: string; -} -" -`; - -exports[`Entity Schematic should update the state to plural 3`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; -import { User } from './user.model'; -import { UserActions } from './user.actions'; - -export const usersFeatureKey = 'users'; - -export interface State extends EntityState { - // additional entities state properties -} - -export const adapter: EntityAdapter = createEntityAdapter(); - -export const initialState: State = adapter.getInitialState({ - // additional entity state properties -}); - -export const reducer = createReducer( - initialState, - on(UserActions.addUser, - (state, action) => adapter.addOne(action.user, state) - ), - on(UserActions.upsertUser, - (state, action) => adapter.upsertOne(action.user, state) - ), - on(UserActions.addUsers, - (state, action) => adapter.addMany(action.users, state) - ), - on(UserActions.upsertUsers, - (state, action) => adapter.upsertMany(action.users, state) - ), - on(UserActions.updateUser, - (state, action) => adapter.updateOne(action.user, state) - ), - on(UserActions.updateUsers, - (state, action) => adapter.updateMany(action.users, state) - ), - on(UserActions.deleteUser, - (state, action) => adapter.removeOne(action.id, state) - ), - on(UserActions.deleteUsers, - (state, action) => adapter.removeMany(action.ids, state) - ), - on(UserActions.loadUsers, - (state, action) => adapter.setAll(action.users, state) - ), - on(UserActions.clearUsers, - state => adapter.removeAll(state) - ), -); - -export const usersFeature = createFeature({ - name: usersFeatureKey, - reducer, - extraSelectors: ({ selectUsersState }) => ({ - ...adapter.getSelectors(selectUsersState) - }), -}); - -export const { - selectIds, - selectEntities, - selectAll, - selectTotal, -} = usersFeature; -" -`; - -exports[`Entity Schematic should update the state to plural 4`] = ` -"import { reducer, initialState } from './user.reducer'; - -describe('User Reducer', () => { - describe('unknown action', () => { - it('should return the previous state', () => { - const action = {} as any; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }); - }); -}); -" -`; - -exports[`Entity Schematic should update the state to plural 5`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; -import * as fromUser from '../user.reducer'; - -export const userFeatureKey = 'user'; - -export interface State { - - [fromUser.usersFeatureKey]: fromUser.State; -} - -export const reducers: ActionReducerMap = { - - [fromUser.usersFeatureKey]: fromUser.reducer, -}; - - export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; " `; diff --git a/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap b/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap index a716c7f0fc..ec63cd0d91 100644 --- a/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/feature/__snapshots__/index.spec.ts.snap @@ -311,315 +311,3 @@ import { App } from './app'; export class AppModule { } " `; - -exports[`Feature Schematic should create all files of a feature with an entity 1`] = ` -"import { createActionGroup, emptyProps, props } from '@ngrx/store'; -import { Update } from '@ngrx/entity'; - -import { Foo } from './foo.model'; - -export const FooActions = createActionGroup({ - source: 'Foo/API', - events: { - 'Load Foos': props<{ foos: Foo[] }>(), - 'Add Foo': props<{ foo: Foo }>(), - 'Upsert Foo': props<{ foo: Foo }>(), - 'Add Foos': props<{ foos: Foo[] }>(), - 'Upsert Foos': props<{ foos: Foo[] }>(), - 'Update Foo': props<{ foo: Update }>(), - 'Update Foos': props<{ foos: Update[] }>(), - 'Delete Foo': props<{ id: string }>(), - 'Delete Foos': props<{ ids: string[] }>(), - 'Clear Foos': emptyProps(), - } -}); -" -`; - -exports[`Feature Schematic should create all files of a feature with an entity 2`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity'; -import { Foo } from './foo.model'; -import { FooActions } from './foo.actions'; - -export const foosFeatureKey = 'foos'; - -export interface State extends EntityState { - // additional entities state properties -} - -export const adapter: EntityAdapter = createEntityAdapter(); - -export const initialState: State = adapter.getInitialState({ - // additional entity state properties -}); - -export const reducer = createReducer( - initialState, - on(FooActions.addFoo, - (state, action) => adapter.addOne(action.foo, state) - ), - on(FooActions.upsertFoo, - (state, action) => adapter.upsertOne(action.foo, state) - ), - on(FooActions.addFoos, - (state, action) => adapter.addMany(action.foos, state) - ), - on(FooActions.upsertFoos, - (state, action) => adapter.upsertMany(action.foos, state) - ), - on(FooActions.updateFoo, - (state, action) => adapter.updateOne(action.foo, state) - ), - on(FooActions.updateFoos, - (state, action) => adapter.updateMany(action.foos, state) - ), - on(FooActions.deleteFoo, - (state, action) => adapter.removeOne(action.id, state) - ), - on(FooActions.deleteFoos, - (state, action) => adapter.removeMany(action.ids, state) - ), - on(FooActions.loadFoos, - (state, action) => adapter.setAll(action.foos, state) - ), - on(FooActions.clearFoos, - state => adapter.removeAll(state) - ), -); - -export const foosFeature = createFeature({ - name: foosFeatureKey, - reducer, - extraSelectors: ({ selectFoosState }) => ({ - ...adapter.getSelectors(selectFoosState) - }), -}); - -export const { - selectIds, - selectEntities, - selectAll, - selectTotal, -} = foosFeature; -" -`; - -exports[`Feature Schematic should create all files of a feature with an entity 3`] = ` -"import { reducer, initialState } from './foo.reducer'; - -describe('Foo Reducer', () => { - describe('unknown action', () => { - it('should return the previous state', () => { - const action = {} as any; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }); - }); -}); -" -`; - -exports[`Feature Schematic should create all files of a feature with an entity 4`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; - -import { concatMap } from 'rxjs/operators'; -import { Observable, EMPTY } from 'rxjs'; -import { FooActions } from './foo.actions'; - -@Injectable() -export class FooEffects { - - - loadFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.loadFoos), - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - concatMap(() => EMPTY as Observable<{ type: string }>) - ); - }); - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Feature Schematic should create all files of a feature with an entity 5`] = ` -"import { TestBed } from '@angular/core/testing'; -import { provideMockActions } from '@ngrx/effects/testing'; -import { Observable } from 'rxjs'; - -import { FooEffects } from './foo.effects'; - -describe('FooEffects', () => { - let actions$: Observable; - let effects: FooEffects; - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - FooEffects, - provideMockActions(() => actions$) - ] - }); - - effects = TestBed.inject(FooEffects); - }); - - it('should be created', () => { - expect(effects).toBeTruthy(); - }); -}); -" -`; - -exports[`Feature Schematic should create all files of a feature with an entity 6`] = ` -"export interface Foo { - id: string; -} -" -`; - -exports[`Feature Schematic should have all api actions in reducer if api flag enabled 1`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { FooActions } from './foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, - on(FooActions.loadFoos, state => state), - on(FooActions.loadFoosSuccess, (state, action) => state), - on(FooActions.loadFoosFailure, (state, action) => state), -); - -export const fooFeature = createFeature({ - name: fooFeatureKey, - reducer, -}); - -" -`; - -exports[`Feature Schematic should have all api actions with prefix in reducer if api flag enabled 1`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { FooActions } from './foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, - on(FooActions.customFoos, state => state), - on(FooActions.customFoosSuccess, (state, action) => state), - on(FooActions.customFoosFailure, (state, action) => state), -); - -export const fooFeature = createFeature({ - name: fooFeatureKey, - reducer, -}); - -" -`; - -exports[`Feature Schematic should have all api effect if api flag enabled 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { catchError, map, concatMap } from 'rxjs/operators'; -import { Observable, EMPTY, of } from 'rxjs'; -import { FooActions } from './foo.actions'; - - -@Injectable() -export class FooEffects { - - loadFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.loadFoos), - concatMap(() => - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - EMPTY.pipe( - map(data => FooActions.loadFoosSuccess({ data })), - catchError(error => of(FooActions.loadFoosFailure({ error })))) - ) - ); - }); - - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Feature Schematic should have all api effect with prefix if api flag enabled 1`] = ` -"import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { catchError, map, concatMap } from 'rxjs/operators'; -import { Observable, EMPTY, of } from 'rxjs'; -import { FooActions } from './foo.actions'; - - -@Injectable() -export class FooEffects { - - customFoos$ = createEffect(() => { - return this.actions$.pipe( - - ofType(FooActions.customFoos), - concatMap(() => - /** An EMPTY observable only emits completion. Replace with your own observable API request */ - EMPTY.pipe( - map(data => FooActions.customFoosSuccess({ data })), - catchError(error => of(FooActions.customFoosFailure({ error })))) - ) - ); - }); - - - constructor(private actions$: Actions) {} -} -" -`; - -exports[`Feature Schematic should respect the path provided for the feature name 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; diff --git a/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap b/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap index 15f4576795..eb39da307f 100644 --- a/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/reducer/__snapshots__/index.spec.ts.snap @@ -207,211 +207,3 @@ import * as fromFoo from './foo.reducer'; export class AppModule { } " `; - -exports[`Reducer Schematic should create a reducer 1`] = ` -"import { createReducer, on } from '@ngrx/store'; -import { FooActions } from './foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, -); - -" -`; - -exports[`Reducer Schematic should create a reducer with prefix in an api feature 1`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { FooActions } from './foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, - on(FooActions.customFoos, state => state), - on(FooActions.customFoosSuccess, (state, action) => state), - on(FooActions.customFoosFailure, (state, action) => state), -); - -export const fooFeature = createFeature({ - name: fooFeatureKey, - reducer, -}); - -" -`; - -exports[`Reducer Schematic should create a reducers barrel file 1`] = ` -" - import { isDevMode } from '@angular/core'; - import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer - } from '@ngrx/store'; -import * as fromFoo from '../foo.reducer'; - - export interface State { - - [fromFoo.fooFeatureKey]: fromFoo.State; -} - - export const reducers: ActionReducerMap = { - - [fromFoo.fooFeatureKey]: fromFoo.reducer, -}; - - - export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; - " -`; - -exports[`Reducer Schematic should create and export a reducer in a feature 1`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { FooActions } from './foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, - on(FooActions.loadFoos, state => state), - -); - -export const fooFeature = createFeature({ - name: fooFeatureKey, - reducer, -}); - -" -`; - -exports[`Reducer Schematic should create and export a reducer in an api feature 1`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { FooActions } from './foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, - on(FooActions.loadFoos, state => state), - on(FooActions.loadFoosSuccess, (state, action) => state), - on(FooActions.loadFoosFailure, (state, action) => state), -); - -export const fooFeature = createFeature({ - name: fooFeatureKey, - reducer, -}); - -" -`; - -exports[`Reducer Schematic should group and nest the reducer within a feature 1`] = ` -"import { createFeature, createReducer, on } from '@ngrx/store'; -import { FooActions } from '../../actions/foo/foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, - on(FooActions.loadFoos, state => state), - -); - -export const fooFeature = createFeature({ - name: fooFeatureKey, - reducer, -}); - -" -`; - -exports[`Reducer Schematic should group within a "reducers" folder if group is set 1`] = ` -"import { createReducer, on } from '@ngrx/store'; -import { FooActions } from '../actions/foo.actions'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const initialState: State = { - -}; - -export const reducer = createReducer( - initialState, -); - -" -`; - -exports[`Reducer Schematic should import into a specified module 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { StoreModule } from '@ngrx/store'; -import * as fromFoo from './foo.reducer'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - StoreModule.forFeature(fromFoo.fooFeatureKey, fromFoo.reducer) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; diff --git a/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap b/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap index ffc96ce7ee..ec64f0cb8c 100644 --- a/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/selector/__snapshots__/index.spec.ts.snap @@ -102,106 +102,3 @@ describe('Foo Selectors', () => { }); " `; - -exports[`Selector Schematic With feature flag should create a selector 1`] = ` -"import { createFeatureSelector, createSelector } from '@ngrx/store'; -import * as fromFoo from './foo.reducer'; - -export const selectFooState = createFeatureSelector( - fromFoo.fooFeatureKey -); -" -`; - -exports[`Selector Schematic With feature flag should create a selector 2`] = ` -"import * as fromFoo from './foo.reducer'; -import { selectFooState } from './foo.selectors'; - -describe('Foo Selectors', () => { - it('should select the feature state', () => { - const result = selectFooState({ - [fromFoo.fooFeatureKey]: {} - }); - - expect(result).toEqual({}); - }); -}); -" -`; - -exports[`Selector Schematic With feature flag should group and nest the selectors within a feature 1`] = ` -"import { createFeatureSelector, createSelector } from '@ngrx/store'; -import * as fromFoo from '../../reducers/foo/foo.reducer'; - -export const selectFooState = createFeatureSelector( - fromFoo.fooFeatureKey -); -" -`; - -exports[`Selector Schematic With feature flag should group and nest the selectors within a feature 2`] = ` -"import * as fromFoo from '../../reducers/foo/foo.reducer'; -import { selectFooState } from './foo.selectors'; - -describe('Foo Selectors', () => { - it('should select the feature state', () => { - const result = selectFooState({ - [fromFoo.fooFeatureKey]: {} - }); - - expect(result).toEqual({}); - }); -}); -" -`; - -exports[`Selector Schematic should create selector files 1`] = ` -"import { createFeatureSelector, createSelector } from '@ngrx/store'; - -" -`; - -exports[`Selector Schematic should create selector files 2`] = ` -" - -describe('Foo Selectors', () => { - it('should select the feature state', () => { - - }); -}); -" -`; - -exports[`Selector Schematic should group selectors if group is true 1`] = ` -"import { createFeatureSelector, createSelector } from '@ngrx/store'; - -" -`; - -exports[`Selector Schematic should group selectors if group is true 2`] = ` -" - -describe('Foo Selectors', () => { - it('should select the feature state', () => { - - }); -}); -" -`; - -exports[`Selector Schematic should not flatten selectors if flat is false 1`] = ` -"import { createFeatureSelector, createSelector } from '@ngrx/store'; - -" -`; - -exports[`Selector Schematic should not flatten selectors if flat is false 2`] = ` -" - -describe('Foo Selectors', () => { - it('should select the feature state', () => { - - }); -}); -" -`; diff --git a/modules/schematics/src/store/__snapshots__/index.spec.ts.snap b/modules/schematics/src/store/__snapshots__/index.spec.ts.snap index 541d87079a..bfbd301865 100644 --- a/modules/schematics/src/store/__snapshots__/index.spec.ts.snap +++ b/modules/schematics/src/store/__snapshots__/index.spec.ts.snap @@ -513,523 +513,6 @@ export const reducers: ActionReducerMap = { }; -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should add a feature key if not root 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should add a feature key if not root 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should add the initial config correctly into an empty module 1`] = ` -" - import { NgModule, isDevMode } from '@angular/core'; -import { StoreModule } from '@ngrx/store'; -import { reducers, metaReducers } from './reducers'; -import { StoreDevtoolsModule } from '@ngrx/store-devtools'; - - @NgModule({ - declarations: [], - imports: [StoreModule.forRoot(reducers, { metaReducers }), isDevMode() ? StoreDevtoolsModule.instrument() : []], - }) - export class EmptyModule {} - " -`; - -exports[`Store Schematic should create the initial store setup 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should create the initial store setup 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should import a feature a specified module 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { StoreModule } from '@ngrx/store'; -import * as fromFoo from './reducers'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - StoreModule.forFeature(fromFoo.fooFeatureKey, fromFoo.reducers, { metaReducers: fromFoo.metaReducers }) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should import a feature a specified module 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should import into a specified module 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners, isDevMode } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { StoreModule } from '@ngrx/store'; -import { reducers, metaReducers } from './reducers'; -import { StoreDevtoolsModule } from '@ngrx/store-devtools'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - StoreModule.forRoot(reducers, { metaReducers }), - isDevMode() ? StoreDevtoolsModule.instrument() : [] - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should import into a specified module 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should not add a feature key if root 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should not add a feature key if root 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should not skip the initial store setup files if the minimal flag is provided with a feature 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { StoreModule } from '@ngrx/store'; -import * as fromFoo from './reducers'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - StoreModule.forFeature(fromFoo.fooFeatureKey, fromFoo.reducers, { metaReducers: fromFoo.metaReducers }) - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should not skip the initial store setup files if the minimal flag is provided with a feature 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - -export const fooFeatureKey = 'foo'; - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should skip the initial store setup files if the minimal flag is provided 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners, isDevMode } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; -import { StoreModule } from '@ngrx/store'; -import { StoreDevtoolsModule } from '@ngrx/store-devtools'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule, - StoreModule.forRoot({}), - isDevMode() ? StoreDevtoolsModule.instrument() : [] - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should support a custom feature state interface name 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should support a custom feature state interface name 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - -export const featureFeatureKey = 'feature'; - -export interface FeatureState { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should support a custom root state interface name 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should support a custom root state interface name 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - - -export interface AppState { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should support a default feature state interface name 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should support a default feature state interface name 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - -export const featureFeatureKey = 'feature'; - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - -export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; -" -`; - -exports[`Store Schematic should support a default root state interface name 1`] = ` -"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { App } from './app'; - -@NgModule({ - declarations: [ - App - ], - imports: [ - BrowserModule - ], - providers: [ - provideBrowserGlobalErrorListeners() - ], - bootstrap: [App] -}) -export class AppModule { } -" -`; - -exports[`Store Schematic should support a default root state interface name 2`] = ` -"import { isDevMode } from '@angular/core'; -import { - ActionReducer, - ActionReducerMap, - createFeatureSelector, - createSelector, - MetaReducer -} from '@ngrx/store'; - - -export interface State { - -} - -export const reducers: ActionReducerMap = { - -}; - - export const metaReducers: MetaReducer[] = isDevMode() ? [] : []; " `;