From 76dc28a0c0d295e6c280a89468333baf4b9b0f13 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Tue, 27 Aug 2024 20:01:51 -0500 Subject: [PATCH 01/11] chore: create shell for `withDataService` promises test --- .../src/lib/with-data-service.spec.ts | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 libs/ngrx-toolkit/src/lib/with-data-service.spec.ts diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts new file mode 100644 index 0000000..12abb55 --- /dev/null +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -0,0 +1,86 @@ +import { + DataService, + withCallState, + withDataService, +} from '@angular-architects/ngrx-toolkit'; +import { signalStore, type } from '@ngrx/signals'; +import { withEntities } from '@ngrx/signals/entities'; +import { Flight } from '../../../../apps/demo/src/app/shared/flight'; +import { Injectable } from '@angular/core'; +import { Observable, firstValueFrom, of } from 'rxjs'; +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { EntityId } from '@ngrx/signals/entities'; + +describe('withDataService', () => { + it('should load from a service and set entities in the store', () => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }), + ); + + const store = new Store(); + + expect(store.entities.length).toBe(0); + + store.load() + + expect(store.entities.length).toBe(1); + }); +}); + +export type FlightFilter = { + from: string; + to: string; +}; + +@Injectable({ + providedIn: 'root', +}) +export class MockFlightService implements DataService { + loadById(id: EntityId): Promise { + return firstValueFrom(this.findById('' + id)); + } + + create(entity: Flight): Promise { + entity.id = 0; + return firstValueFrom(this.save(entity)); + } + + update(entity: Flight): Promise { + return firstValueFrom(this.save(entity)); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + updateAll(entity: Flight[]): Promise { + throw new Error('updateAll method not implemented.'); + } + + delete(entity: Flight): Promise { + return firstValueFrom(this.remove(entity)); + } + + load(filter: FlightFilter): Promise { + return firstValueFrom(this.find(filter.from, filter.to)); + } + + private find(from: string, to: string, urgent = false): Observable { + return of([{id: 1, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false}]) + } + + private findById(id: string): Observable { + return of({id: 2, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false}) + } + + private save(flight: Flight): Observable { + return of({id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false}) + } + + private remove(flight: Flight): Observable { + return of() + } +} From 02df49a49aa14fe182386509a56ef78200705d0e Mon Sep 17 00:00:00 2001 From: Michael Small Date: Tue, 27 Aug 2024 20:23:33 -0500 Subject: [PATCH 02/11] chore: embed first test of `withDataService` in `fakeAsync`, clean up imports --- .../src/lib/with-data-service.spec.ts | 90 ++++++++++++------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index 12abb55..fa23c5c 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -1,36 +1,35 @@ -import { - DataService, - withCallState, - withDataService, -} from '@angular-architects/ngrx-toolkit'; -import { signalStore, type } from '@ngrx/signals'; +import { signalStore } from '@ngrx/signals'; import { withEntities } from '@ngrx/signals/entities'; -import { Flight } from '../../../../apps/demo/src/app/shared/flight'; import { Injectable } from '@angular/core'; import { Observable, firstValueFrom, of } from 'rxjs'; -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { EntityId } from '@ngrx/signals/entities'; +import { fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { withCallState } from './with-call-state'; +import { DataService, withDataService } from './with-data-service'; describe('withDataService', () => { - it('should load from a service and set entities in the store', () => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }), - ); - - const store = new Store(); - - expect(store.entities.length).toBe(0); - - store.load() - - expect(store.entities.length).toBe(1); - }); + it('should load from a service and set entities in the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }) + ); + const store = new Store(); + + tick(1); + expect(store.entities().length).toBe(0); + + store.load(); + tick(1); + + expect(store.entities().length).toBe(1); + }); + })); }); export type FlightFilter = { @@ -69,18 +68,47 @@ export class MockFlightService implements DataService { } private find(from: string, to: string, urgent = false): Observable { - return of([{id: 1, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false}]) + console.log('hey', from, to); + return of([ + { + id: 1, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]); } private findById(id: string): Observable { - return of({id: 2, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false}) + return of({ + id: 2, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); } private save(flight: Flight): Observable { - return of({id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false}) + return of({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); } private remove(flight: Flight): Observable { - return of() + return of(); } } + +export type Flight = { + id: number; + from: string; + to: string; + date: string; + delayed: boolean; +}; From d1a214c22b2f8fb2ed2a63ea1b5fd7ac2743eead Mon Sep 17 00:00:00 2001 From: Michael Small Date: Tue, 27 Aug 2024 23:51:34 -0500 Subject: [PATCH 03/11] test(dataService): add `loadById` test (no prefix), and note on test expecations --- .../src/lib/with-data-service.spec.ts | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index fa23c5c..ed16027 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -1,12 +1,16 @@ -import { signalStore } from '@ngrx/signals'; -import { withEntities } from '@ngrx/signals/entities'; import { Injectable } from '@angular/core'; +import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { Observable, firstValueFrom, of } from 'rxjs'; +import { signalStore } from '@ngrx/signals'; +import { withEntities } from '@ngrx/signals/entities'; import { EntityId } from '@ngrx/signals/entities'; -import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { withCallState } from './with-call-state'; import { DataService, withDataService } from './with-data-service'; +// Since the resulting shape of entities in the store is a matter of the implementing services of `dataServiceType`, +// these tests are more so about verifying that each resulting method exists, with or without prefixes. +// The expectations on the resulting shape of the data in the store following these tests merely asserts +// that the store was patched in the right generic shape and with respective call states. describe('withDataService', () => { it('should load from a service and set entities in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { @@ -30,9 +34,37 @@ describe('withDataService', () => { expect(store.entities().length).toBe(1); }); })); + it('should load by ID from a service and set entities in the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }) + ); + const store = new Store(); + + tick(1); + + store.loadById(2); + + tick(1); + + expect(store.current()).toEqual({ + id: 2, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + }); + })); }); -export type FlightFilter = { +type FlightFilter = { from: string; to: string; }; @@ -40,7 +72,7 @@ export type FlightFilter = { @Injectable({ providedIn: 'root', }) -export class MockFlightService implements DataService { +class MockFlightService implements DataService { loadById(id: EntityId): Promise { return firstValueFrom(this.findById('' + id)); } @@ -68,7 +100,6 @@ export class MockFlightService implements DataService { } private find(from: string, to: string, urgent = false): Observable { - console.log('hey', from, to); return of([ { id: 1, @@ -105,7 +136,7 @@ export class MockFlightService implements DataService { } } -export type Flight = { +type Flight = { id: number; from: string; to: string; From 63171d18b5ae49fcd1f65e19d148fa4ea644b36f Mon Sep 17 00:00:00 2001 From: Michael Small Date: Wed, 28 Aug 2024 21:17:17 -0500 Subject: [PATCH 04/11] test(dataService): add create/update/updateAll/delete tests (w/o prefix) --- .../src/lib/with-data-service.spec.ts | 202 +++++++++++++++++- 1 file changed, 200 insertions(+), 2 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index ed16027..cd4251d 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -62,6 +62,192 @@ describe('withDataService', () => { }); }); })); + it('should create from a service and set an entity in the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }) + ); + const store = new Store(); + + tick(1); + + expect(store.entities().length).toBe(0) + + store.create({ + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + } as Flight) + + tick(1); + + expect(store.entities().length).toBe(1) + expect(store.current()).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); + it('should update from a service and update an entity in the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }) + ); + const store = new Store(); + + tick(1); + + expect(store.entities().length).toBe(0) + + store.create({ + id: 3, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + store.update({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + + expect(store.current()).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); + it('should update all from a service and update all entities in the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }) + ); + const store = new Store(); + + tick(1); + + expect(store.entities().length).toBe(0) + + store.create({ + id: 3, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + store.create({ + id: 4, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + store.updateAll([{ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }]) + tick(1); + expect(store.entities().length).toBe(2) + expect(store.entities().at(0)).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + expect(store.entities().at(1)).toEqual({ + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); + it('should delete from a service and update that entity in the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const Store = signalStore( + { providedIn: 'root' }, + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }) + ); + const store = new Store(); + + tick(1); + + expect(store.entities().length).toBe(0) + + store.create({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + expect(store.entities().length).toBe(1) + expect(store.entities().at(0)).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + store.delete({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + expect(store.entities().length).toBe(0) + }); + })); }); type FlightFilter = { @@ -88,7 +274,19 @@ class MockFlightService implements DataService { // eslint-disable-next-line @typescript-eslint/no-unused-vars updateAll(entity: Flight[]): Promise { - throw new Error('updateAll method not implemented.'); + return firstValueFrom(of([{ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }])); } delete(entity: Flight): Promise { @@ -132,7 +330,7 @@ class MockFlightService implements DataService { } private remove(flight: Flight): Observable { - return of(); + return of(undefined); } } From 54b8b6201a7d656e0b5b77918ccb29326b626a24 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Thu, 29 Aug 2024 21:22:29 -0500 Subject: [PATCH 05/11] test(dataService): add tests with collection name --- .../src/lib/with-data-service.spec.ts | 264 ++++++++++++++---- 1 file changed, 208 insertions(+), 56 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index cd4251d..27d2982 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -1,28 +1,20 @@ import { Injectable } from '@angular/core'; import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { Observable, firstValueFrom, of } from 'rxjs'; -import { signalStore } from '@ngrx/signals'; +import { signalStore, type, withHooks } from '@ngrx/signals'; import { withEntities } from '@ngrx/signals/entities'; import { EntityId } from '@ngrx/signals/entities'; import { withCallState } from './with-call-state'; import { DataService, withDataService } from './with-data-service'; // Since the resulting shape of entities in the store is a matter of the implementing services of `dataServiceType`, -// these tests are more so about verifying that each resulting method exists, with or without prefixes. +// these tests are more so about verifying that each resulting method exists, with or without named collections. // The expectations on the resulting shape of the data in the store following these tests merely asserts // that the store was patched in the right generic shape and with respective call states. + describe('withDataService', () => { it('should load from a service and set entities in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }) - ); const store = new Store(); tick(1); @@ -34,17 +26,21 @@ describe('withDataService', () => { expect(store.entities().length).toBe(1); }); })); + it('should load from a service and set entities in the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + expect(store.flightEntities().length).toBe(0); + + store.loadFlightEntities(); + tick(1); + + expect(store.flightEntities().length).toBe(1); + }); + })); it('should load by ID from a service and set entities in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }) - ); const store = new Store(); tick(1); @@ -62,17 +58,27 @@ describe('withDataService', () => { }); }); })); + it('should load by ID from a service and set entities in the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + store.loadFlightById(2); + + tick(1); + + expect(store.currentFlight()).toEqual({ + id: 2, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + }); + })); it('should create from a service and set an entity in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }) - ); const store = new Store(); tick(1); @@ -98,17 +104,35 @@ describe('withDataService', () => { }) }); })); + it('should create from a service and set an entity in the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + expect(store.flightEntities().length).toBe(0) + + store.createFlight({ + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + } as Flight) + + tick(1); + + expect(store.flightEntities().length).toBe(1) + expect(store.currentFlight()).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); it('should update from a service and update an entity in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }) - ); const store = new Store(); tick(1); @@ -141,17 +165,42 @@ describe('withDataService', () => { }) }); })); + it('should update from a service and update an entity in the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + expect(store.flightEntities().length).toBe(0) + + store.createFlight({ + id: 3, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + store.updateFlight({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + + expect(store.currentFlight()).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); it('should update all from a service and update all entities in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }) - ); const store = new Store(); tick(1); @@ -204,17 +253,62 @@ describe('withDataService', () => { }) }); })); + it('should update all from a service and update all entities in the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + expect(store.flightEntities().length).toBe(0) + + store.createFlight({ + id: 3, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + store.createFlight({ + id: 4, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + store.updateAllFlight([{ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }]) + tick(1); + expect(store.flightEntities().length).toBe(2) + expect(store.flightEntities().at(0)).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + expect(store.flightEntities().at(1)).toEqual({ + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); it('should delete from a service and update that entity in the store', fakeAsync(() => { TestBed.runInInjectionContext(() => { - const Store = signalStore( - { providedIn: 'root' }, - withCallState(), - withEntities(), - withDataService({ - dataServiceType: MockFlightService, - filter: { from: 'Paris', to: 'New York' }, - }) - ); const store = new Store(); tick(1); @@ -248,6 +342,41 @@ describe('withDataService', () => { expect(store.entities().length).toBe(0) }); })); + it('should delete from a service and update that entity in the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + expect(store.flightEntities().length).toBe(0) + + store.createFlight({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + expect(store.flightEntities().length).toBe(1) + expect(store.flightEntities().at(0)).toEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + store.deleteFlight({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + tick(1); + expect(store.flightEntities().length).toBe(0) + }); + })); }); type FlightFilter = { @@ -341,3 +470,26 @@ type Flight = { date: string; delayed: boolean; }; + +const Store = signalStore( + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + }), +); +const StoreWithNamedCollection = signalStore( + withCallState({ + collection: 'flight' + }), + withEntities({ + entity: type(), + collection: 'flight' + }), + withDataService({ + dataServiceType: MockFlightService, + filter: { from: 'Paris', to: 'New York' }, + collection: 'flight', + }), +); From 1ea595aa2406a4e8d2d68173a628074a82528f98 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Thu, 29 Aug 2024 21:44:34 -0500 Subject: [PATCH 06/11] test(dataService): add tests for selected/filter (with and w/o collection name) --- .../src/lib/with-data-service.spec.ts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index 27d2982..fda1eaa 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -377,6 +377,94 @@ describe('withDataService', () => { expect(store.flightEntities().length).toBe(0) }); })); + it('should update the selected flight of the store', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new Store(); + + tick(1); + + store.create({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + expect(store.selectedEntities().length).toBe(0) + + store.updateSelected(3, true) + + tick(1); + + expect(store.selectedEntities().length).toBe(1) + expect(store.selectedEntities()).toContainEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); + it('should update selected flight of the store (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + store.createFlight({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + expect(store.selectedFlightEntities().length).toBe(0) + + store.updateSelectedFlightEntities(3, true) + + tick(1); + + expect(store.selectedFlightEntities().length).toBe(1) + expect(store.selectedFlightEntities()).toContainEqual({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }) + }); + })); + it('should update the filter of the service', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new Store(); + + tick(1); + + expect(store.filter()).toEqual({ from: 'Paris', to: 'New York' }) + + store.updateFilter({ from: 'Wadena MN', to: 'New York' }) + + tick(1); + + expect(store.filter()).toEqual({ from: 'Wadena MN', to: 'New York' }) + }); + })); + it('should update the filter of the service (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); + + tick(1); + + expect(store.flightFilter()).toEqual({ from: 'Paris', to: 'New York' }) + + store.updateFlightFilter({ from: 'Wadena MN', to: 'New York' }) + + tick(1); + + expect(store.flightFilter()).toEqual({ from: 'Wadena MN', to: 'New York' }) + }); + })); }); type FlightFilter = { From ffe5add502178b534dbc3eef61445f5f9e23f49b Mon Sep 17 00:00:00 2001 From: Michael Small Date: Sun, 1 Sep 2024 12:37:30 -0500 Subject: [PATCH 07/11] test(dataService): add tests for current entity, and loading states --- .../src/lib/with-data-service.spec.ts | 532 ++++++++++++++---- 1 file changed, 434 insertions(+), 98 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index fda1eaa..ee9d12a 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { Observable, firstValueFrom, of } from 'rxjs'; -import { signalStore, type, withHooks } from '@ngrx/signals'; +import { Observable, firstValueFrom, of, delay } from 'rxjs'; +import { signalStore, type } from '@ngrx/signals'; import { withEntities } from '@ngrx/signals/entities'; import { EntityId } from '@ngrx/signals/entities'; import { withCallState } from './with-call-state'; @@ -83,25 +83,25 @@ describe('withDataService', () => { tick(1); - expect(store.entities().length).toBe(0) + expect(store.entities().length).toBe(0); store.create({ from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - } as Flight) + } as Flight); tick(1); - expect(store.entities().length).toBe(1) + expect(store.entities().length).toBe(1); expect(store.current()).toEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should create from a service and set an entity in the store (with named collection)', fakeAsync(() => { @@ -110,25 +110,25 @@ describe('withDataService', () => { tick(1); - expect(store.flightEntities().length).toBe(0) + expect(store.flightEntities().length).toBe(0); store.createFlight({ from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - } as Flight) + } as Flight); tick(1); - expect(store.flightEntities().length).toBe(1) + expect(store.flightEntities().length).toBe(1); expect(store.currentFlight()).toEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should update from a service and update an entity in the store', fakeAsync(() => { @@ -137,7 +137,7 @@ describe('withDataService', () => { tick(1); - expect(store.entities().length).toBe(0) + expect(store.entities().length).toBe(0); store.create({ id: 3, @@ -145,7 +145,7 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); store.update({ id: 3, @@ -153,7 +153,7 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); expect(store.current()).toEqual({ @@ -162,7 +162,7 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should update from a service and update an entity in the store (with named collection)', fakeAsync(() => { @@ -171,7 +171,7 @@ describe('withDataService', () => { tick(1); - expect(store.flightEntities().length).toBe(0) + expect(store.flightEntities().length).toBe(0); store.createFlight({ id: 3, @@ -179,7 +179,7 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); store.updateFlight({ id: 3, @@ -187,7 +187,7 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); expect(store.currentFlight()).toEqual({ @@ -196,7 +196,7 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should update all from a service and update all entities in the store', fakeAsync(() => { @@ -205,7 +205,7 @@ describe('withDataService', () => { tick(1); - expect(store.entities().length).toBe(0) + expect(store.entities().length).toBe(0); store.create({ id: 3, @@ -213,44 +213,47 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); store.create({ id: 4, from: 'Wadena MN', to: 'New York', date: new Date().toDateString(), delayed: false, - }) - tick(1); - store.updateAll([{ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }]) + }); tick(1); - expect(store.entities().length).toBe(2) + store.updateAll([ + { + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]); + tick(1); + expect(store.entities().length).toBe(2); expect(store.entities().at(0)).toEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); expect(store.entities().at(1)).toEqual({ id: 4, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should update all from a service and update all entities in the store (with named collection)', fakeAsync(() => { @@ -259,7 +262,7 @@ describe('withDataService', () => { tick(1); - expect(store.flightEntities().length).toBe(0) + expect(store.flightEntities().length).toBe(0); store.createFlight({ id: 3, @@ -267,44 +270,47 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); store.createFlight({ id: 4, from: 'Wadena MN', to: 'New York', date: new Date().toDateString(), delayed: false, - }) - tick(1); - store.updateAllFlight([{ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }]) + }); tick(1); - expect(store.flightEntities().length).toBe(2) + store.updateAllFlight([ + { + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]); + tick(1); + expect(store.flightEntities().length).toBe(2); expect(store.flightEntities().at(0)).toEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); expect(store.flightEntities().at(1)).toEqual({ id: 4, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should delete from a service and update that entity in the store', fakeAsync(() => { @@ -313,7 +319,7 @@ describe('withDataService', () => { tick(1); - expect(store.entities().length).toBe(0) + expect(store.entities().length).toBe(0); store.create({ id: 3, @@ -321,25 +327,25 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); - expect(store.entities().length).toBe(1) + expect(store.entities().length).toBe(1); expect(store.entities().at(0)).toEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); store.delete({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); - expect(store.entities().length).toBe(0) + expect(store.entities().length).toBe(0); }); })); it('should delete from a service and update that entity in the store (with named collection)', fakeAsync(() => { @@ -348,7 +354,7 @@ describe('withDataService', () => { tick(1); - expect(store.flightEntities().length).toBe(0) + expect(store.flightEntities().length).toBe(0); store.createFlight({ id: 3, @@ -356,25 +362,25 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); - expect(store.flightEntities().length).toBe(1) + expect(store.flightEntities().length).toBe(1); expect(store.flightEntities().at(0)).toEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); store.deleteFlight({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); tick(1); - expect(store.flightEntities().length).toBe(0) + expect(store.flightEntities().length).toBe(0); }); })); it('should update the selected flight of the store', fakeAsync(() => { @@ -389,21 +395,21 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) - expect(store.selectedEntities().length).toBe(0) + }); + expect(store.selectedEntities().length).toBe(0); - store.updateSelected(3, true) + store.updateSelected(3, true); tick(1); - expect(store.selectedEntities().length).toBe(1) + expect(store.selectedEntities().length).toBe(1); expect(store.selectedEntities()).toContainEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should update selected flight of the store (with named collection)', fakeAsync(() => { @@ -418,21 +424,21 @@ describe('withDataService', () => { to: 'New York', date: new Date().toDateString(), delayed: false, - }) - expect(store.selectedFlightEntities().length).toBe(0) + }); + expect(store.selectedFlightEntities().length).toBe(0); - store.updateSelectedFlightEntities(3, true) + store.updateSelectedFlightEntities(3, true); tick(1); - expect(store.selectedFlightEntities().length).toBe(1) + expect(store.selectedFlightEntities().length).toBe(1); expect(store.selectedFlightEntities()).toContainEqual({ id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }) + }); }); })); it('should update the filter of the service', fakeAsync(() => { @@ -441,13 +447,13 @@ describe('withDataService', () => { tick(1); - expect(store.filter()).toEqual({ from: 'Paris', to: 'New York' }) + expect(store.filter()).toEqual({ from: 'Paris', to: 'New York' }); - store.updateFilter({ from: 'Wadena MN', to: 'New York' }) + store.updateFilter({ from: 'Wadena MN', to: 'New York' }); tick(1); - expect(store.filter()).toEqual({ from: 'Wadena MN', to: 'New York' }) + expect(store.filter()).toEqual({ from: 'Wadena MN', to: 'New York' }); }); })); it('should update the filter of the service (with named collection)', fakeAsync(() => { @@ -456,15 +462,233 @@ describe('withDataService', () => { tick(1); - expect(store.flightFilter()).toEqual({ from: 'Paris', to: 'New York' }) + expect(store.flightFilter()).toEqual({ from: 'Paris', to: 'New York' }); + + store.updateFlightFilter({ from: 'Wadena MN', to: 'New York' }); + + tick(1); + + expect(store.flightFilter()).toEqual({ + from: 'Wadena MN', + to: 'New York', + }); + }); + })); + it('should the current entity', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new Store(); + tick(1); + + store.create({ + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + } as Flight); - store.updateFlightFilter({ from: 'Wadena MN', to: 'New York' }) + store.setCurrent({ + id: 4, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + expect(store.current()).toEqual({ + id: 4, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + }); + })); + it('set the current entity (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollection(); tick(1); - expect(store.flightFilter()).toEqual({ from: 'Wadena MN', to: 'New York' }) + store.createFlight({ + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + } as Flight); + + store.setCurrentFlight({ + id: 4, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + + expect(store.currentFlight()).toEqual({ + id: 4, + from: 'Wadena MN', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); }); })); + + it('handles loading state', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreForLoading(); + tick(1); + + expect(store.loading()).toBe(false); + + store.create({ + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + } as Flight); + tick(1); + expect(store.loading()).toBe(true); + tick(2); + expect(store.loading()).toBe(false); + + store.load(); + tick(1); + expect(store.loading()).toBe(true); + tick(2); + expect(store.loading()).toBe(false); + + store.loadById(3); + tick(1); + expect(store.loading()).toBe(true); + tick(2); + expect(store.loading()).toBe(false); + + store.update({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + tick(1); + expect(store.loading()).toBe(true); + tick(2); + expect(store.loading()).toBe(false); + + store.updateAll([ + { + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]); + tick(1); + expect(store.loading()).toBe(true); + tick(2); + expect(store.loading()).toBe(false); + + store.delete({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + tick(1); + expect(store.loading()).toBe(true); + tick(2); + expect(store.loading()).toBe(false); + }); + })); + + it('handles loading state (with named collection)', fakeAsync(() => { + TestBed.runInInjectionContext(() => { + const store = new StoreWithNamedCollectionForLoading(); + tick(1); + + expect(store.flightLoading()).toBe(false); + + store.createFlight({ + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + } as Flight); + tick(1); + expect(store.flightLoading()).toBe(true); + tick(2); + expect(store.flightLoading()).toBe(false); + + store.loadFlightEntities(); + tick(1); + expect(store.flightLoading()).toBe(true); + tick(2); + expect(store.flightLoading()).toBe(false); + + store.loadFlightById(3); + tick(1); + expect(store.flightLoading()).toBe(true); + tick(2); + expect(store.flightLoading()).toBe(false); + + store.updateFlight({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + tick(1); + expect(store.flightLoading()).toBe(true); + tick(2); + expect(store.flightLoading()).toBe(false); + + store.updateAllFlight([ + { + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]); + tick(1); + expect(store.flightLoading()).toBe(true); + tick(2); + expect(store.flightLoading()).toBe(false); + + store.deleteFlight({ + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }); + tick(1); + expect(store.flightLoading()).toBe(true); + tick(2); + expect(store.flightLoading()).toBe(false); + }); + })); + + // TODO 3A: setting error state (without named collection) + // TODO 3B: setting error state (with named collection) }); type FlightFilter = { @@ -491,19 +715,108 @@ class MockFlightService implements DataService { // eslint-disable-next-line @typescript-eslint/no-unused-vars updateAll(entity: Flight[]): Promise { - return firstValueFrom(of([{ - id: 3, + return firstValueFrom( + of([ + { + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]) + ); + } + + delete(entity: Flight): Promise { + return firstValueFrom(this.remove(entity)); + } + + load(filter: FlightFilter): Promise { + return firstValueFrom(this.find(filter.from, filter.to)); + } + + private find(from: string, to: string, urgent = false): Observable { + return of([ + { + id: 1, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]); + } + + private findById(id: string): Observable { + return of({ + id: 2, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }, { - id: 4, + }); + } + + private save(flight: Flight): Observable { + return of({ + id: 3, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, - }])); + }); + } + + private remove(flight: Flight): Observable { + return of(undefined); + } +} + +@Injectable({ + providedIn: 'root', +}) +class MockFlightServiceForLoading implements DataService { + loadById(id: EntityId): Promise { + return firstValueFrom(this.findById('' + id)); + } + + create(entity: Flight): Promise { + entity.id = 0; + return firstValueFrom(this.save(entity)); + } + + update(entity: Flight): Promise { + return firstValueFrom(this.save(entity)); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + updateAll(entity: Flight[]): Promise { + return firstValueFrom( + of([ + { + id: 3, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + { + id: 4, + from: 'Paris', + to: 'New York', + date: new Date().toDateString(), + delayed: false, + }, + ]).pipe(delay(3)) + ); } delete(entity: Flight): Promise { @@ -523,7 +836,7 @@ class MockFlightService implements DataService { date: new Date().toDateString(), delayed: false, }, - ]); + ]).pipe(delay(3)); } private findById(id: string): Observable { @@ -533,7 +846,7 @@ class MockFlightService implements DataService { to: 'New York', date: new Date().toDateString(), delayed: false, - }); + }).pipe(delay(3)); } private save(flight: Flight): Observable { @@ -543,11 +856,11 @@ class MockFlightService implements DataService { to: 'New York', date: new Date().toDateString(), delayed: false, - }); + }).pipe(delay(3)); } private remove(flight: Flight): Observable { - return of(undefined); + return of(undefined).pipe(delay(3)); } } @@ -565,19 +878,42 @@ const Store = signalStore( withDataService({ dataServiceType: MockFlightService, filter: { from: 'Paris', to: 'New York' }, - }), + }) ); const StoreWithNamedCollection = signalStore( withCallState({ - collection: 'flight' + collection: 'flight', }), withEntities({ entity: type(), - collection: 'flight' + collection: 'flight', }), withDataService({ dataServiceType: MockFlightService, filter: { from: 'Paris', to: 'New York' }, collection: 'flight', + }) +); + +const StoreForLoading = signalStore( + withCallState(), + withEntities(), + withDataService({ + dataServiceType: MockFlightServiceForLoading, + filter: { from: 'Paris', to: 'New York' }, + }) +); +const StoreWithNamedCollectionForLoading = signalStore( + withCallState({ + collection: 'flight', + }), + withEntities({ + entity: type(), + collection: 'flight', }), + withDataService({ + dataServiceType: MockFlightServiceForLoading, + filter: { from: 'Paris', to: 'New York' }, + collection: 'flight', + }) ); From 11e181e6603e8ab82269798f53dc853a421bafa6 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Mon, 23 Sep 2024 18:33:30 -0500 Subject: [PATCH 08/11] test(dataService): remove must time params passed to `tick` PR comment: "tick() should be sufficient. That applies to all your tests." Change: Most uses of `tick(...)` were replaced, but ones that were time-sensitive to the mocks for loading time were retained --- .../src/lib/with-data-service.spec.ts | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index ee9d12a..9ec9cfe 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -17,11 +17,11 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); expect(store.entities().length).toBe(0); store.load(); - tick(1); + tick(); expect(store.entities().length).toBe(1); }); @@ -30,11 +30,11 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); expect(store.flightEntities().length).toBe(0); store.loadFlightEntities(); - tick(1); + tick(); expect(store.flightEntities().length).toBe(1); }); @@ -43,11 +43,11 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); store.loadById(2); - tick(1); + tick(); expect(store.current()).toEqual({ id: 2, @@ -62,11 +62,11 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); store.loadFlightById(2); - tick(1); + tick(); expect(store.currentFlight()).toEqual({ id: 2, @@ -81,7 +81,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); expect(store.entities().length).toBe(0); @@ -92,7 +92,7 @@ describe('withDataService', () => { delayed: false, } as Flight); - tick(1); + tick(); expect(store.entities().length).toBe(1); expect(store.current()).toEqual({ @@ -108,7 +108,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); expect(store.flightEntities().length).toBe(0); @@ -119,7 +119,7 @@ describe('withDataService', () => { delayed: false, } as Flight); - tick(1); + tick(); expect(store.flightEntities().length).toBe(1); expect(store.currentFlight()).toEqual({ @@ -135,7 +135,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); expect(store.entities().length).toBe(0); @@ -146,7 +146,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); store.update({ id: 3, from: 'Paris', @@ -154,7 +154,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.current()).toEqual({ id: 3, @@ -169,7 +169,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); expect(store.flightEntities().length).toBe(0); @@ -180,7 +180,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); store.updateFlight({ id: 3, from: 'Paris', @@ -188,7 +188,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.currentFlight()).toEqual({ id: 3, @@ -203,7 +203,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); expect(store.entities().length).toBe(0); @@ -221,7 +221,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); store.updateAll([ { id: 3, @@ -238,7 +238,7 @@ describe('withDataService', () => { delayed: false, }, ]); - tick(1); + tick(); expect(store.entities().length).toBe(2); expect(store.entities().at(0)).toEqual({ id: 3, @@ -260,7 +260,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); expect(store.flightEntities().length).toBe(0); @@ -278,7 +278,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); store.updateAllFlight([ { id: 3, @@ -295,7 +295,7 @@ describe('withDataService', () => { delayed: false, }, ]); - tick(1); + tick(); expect(store.flightEntities().length).toBe(2); expect(store.flightEntities().at(0)).toEqual({ id: 3, @@ -317,7 +317,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); expect(store.entities().length).toBe(0); @@ -328,7 +328,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.entities().length).toBe(1); expect(store.entities().at(0)).toEqual({ id: 3, @@ -344,7 +344,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.entities().length).toBe(0); }); })); @@ -352,7 +352,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); expect(store.flightEntities().length).toBe(0); @@ -363,7 +363,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.flightEntities().length).toBe(1); expect(store.flightEntities().at(0)).toEqual({ id: 3, @@ -379,7 +379,7 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.flightEntities().length).toBe(0); }); })); @@ -387,7 +387,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); store.create({ id: 3, @@ -400,7 +400,7 @@ describe('withDataService', () => { store.updateSelected(3, true); - tick(1); + tick(); expect(store.selectedEntities().length).toBe(1); expect(store.selectedEntities()).toContainEqual({ @@ -416,7 +416,7 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); store.createFlight({ id: 3, @@ -429,7 +429,7 @@ describe('withDataService', () => { store.updateSelectedFlightEntities(3, true); - tick(1); + tick(); expect(store.selectedFlightEntities().length).toBe(1); expect(store.selectedFlightEntities()).toContainEqual({ @@ -445,13 +445,13 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); expect(store.filter()).toEqual({ from: 'Paris', to: 'New York' }); store.updateFilter({ from: 'Wadena MN', to: 'New York' }); - tick(1); + tick(); expect(store.filter()).toEqual({ from: 'Wadena MN', to: 'New York' }); }); @@ -460,13 +460,13 @@ describe('withDataService', () => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); expect(store.flightFilter()).toEqual({ from: 'Paris', to: 'New York' }); store.updateFlightFilter({ from: 'Wadena MN', to: 'New York' }); - tick(1); + tick(); expect(store.flightFilter()).toEqual({ from: 'Wadena MN', @@ -477,7 +477,7 @@ describe('withDataService', () => { it('should the current entity', fakeAsync(() => { TestBed.runInInjectionContext(() => { const store = new Store(); - tick(1); + tick(); store.create({ from: 'Paris', @@ -506,7 +506,7 @@ describe('withDataService', () => { it('set the current entity (with named collection)', fakeAsync(() => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); - tick(1); + tick(); store.createFlight({ from: 'Paris', @@ -536,7 +536,7 @@ describe('withDataService', () => { it('handles loading state', fakeAsync(() => { TestBed.runInInjectionContext(() => { const store = new StoreForLoading(); - tick(1); + tick(); expect(store.loading()).toBe(false); @@ -546,21 +546,21 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, } as Flight); - tick(1); + tick(); expect(store.loading()).toBe(true); - tick(2); + tick(3); expect(store.loading()).toBe(false); store.load(); - tick(1); + tick(); expect(store.loading()).toBe(true); - tick(2); + tick(3); expect(store.loading()).toBe(false); store.loadById(3); - tick(1); + tick(); expect(store.loading()).toBe(true); - tick(2); + tick(3); expect(store.loading()).toBe(false); store.update({ @@ -570,9 +570,9 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.loading()).toBe(true); - tick(2); + tick(3); expect(store.loading()).toBe(false); store.updateAll([ @@ -591,9 +591,9 @@ describe('withDataService', () => { delayed: false, }, ]); - tick(1); + tick(); expect(store.loading()).toBe(true); - tick(2); + tick(3); expect(store.loading()).toBe(false); store.delete({ @@ -603,9 +603,9 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.loading()).toBe(true); - tick(2); + tick(3); expect(store.loading()).toBe(false); }); })); @@ -613,7 +613,7 @@ describe('withDataService', () => { it('handles loading state (with named collection)', fakeAsync(() => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollectionForLoading(); - tick(1); + tick(); expect(store.flightLoading()).toBe(false); @@ -623,21 +623,21 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, } as Flight); - tick(1); + tick(); expect(store.flightLoading()).toBe(true); - tick(2); + tick(3); expect(store.flightLoading()).toBe(false); store.loadFlightEntities(); - tick(1); + tick(); expect(store.flightLoading()).toBe(true); - tick(2); + tick(3); expect(store.flightLoading()).toBe(false); store.loadFlightById(3); - tick(1); + tick(); expect(store.flightLoading()).toBe(true); - tick(2); + tick(3); expect(store.flightLoading()).toBe(false); store.updateFlight({ @@ -647,9 +647,9 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.flightLoading()).toBe(true); - tick(2); + tick(3); expect(store.flightLoading()).toBe(false); store.updateAllFlight([ @@ -668,9 +668,9 @@ describe('withDataService', () => { delayed: false, }, ]); - tick(1); + tick(); expect(store.flightLoading()).toBe(true); - tick(2); + tick(3); expect(store.flightLoading()).toBe(false); store.deleteFlight({ @@ -680,9 +680,9 @@ describe('withDataService', () => { date: new Date().toDateString(), delayed: false, }); - tick(1); + tick(); expect(store.flightLoading()).toBe(true); - tick(2); + tick(3); expect(store.flightLoading()).toBe(false); }); })); From c502361a204b23417eadaee8ce5a585c98b7c902 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Mon, 23 Sep 2024 18:52:09 -0500 Subject: [PATCH 09/11] test(dataService): make flight factory function PR comment: I'd create a factory function which generates you a flight. That function should use by a default an default flight object and increments the id automatically with every call. Its signature could be createFlight(flight: Partial): Flight. As you see, you then only need to provide those values of Flight which differ from the default one. Change: Made same function. --- .../src/lib/with-data-service.spec.ts | 110 ++++-------------- 1 file changed, 24 insertions(+), 86 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index 9ec9cfe..2ba3b2e 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -691,6 +691,22 @@ describe('withDataService', () => { // TODO 3B: setting error state (with named collection) }); +// Test helpers +let currentFlightId = 0; +const createFlight = (flight: Partial = {}) => ({ + ...{ + id: ++currentFlightId, from: 'Paris', to: 'New York', date: new Date().toDateString(), delayed: false, + }, + ...flight +}); +type Flight = { + id: number; + from: string; + to: string; + date: string; + delayed: boolean; +}; + type FlightFilter = { from: string; to: string; @@ -716,22 +732,7 @@ class MockFlightService implements DataService { // eslint-disable-next-line @typescript-eslint/no-unused-vars updateAll(entity: Flight[]): Promise { return firstValueFrom( - of([ - { - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - ]) + of([createFlight({id: 3}), createFlight({id: 4})]) ); } @@ -744,35 +745,15 @@ class MockFlightService implements DataService { } private find(from: string, to: string, urgent = false): Observable { - return of([ - { - id: 1, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - ]); + return of([createFlight()]); } private findById(id: string): Observable { - return of({ - id: 2, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + return of(createFlight({id: 2})); } private save(flight: Flight): Observable { - return of({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + return of(createFlight({id: 3})); } private remove(flight: Flight): Observable { @@ -800,22 +781,7 @@ class MockFlightServiceForLoading implements DataService { // eslint-disable-next-line @typescript-eslint/no-unused-vars updateAll(entity: Flight[]): Promise { return firstValueFrom( - of([ - { - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - ]).pipe(delay(3)) + of([createFlight({id: 3}), createFlight({id: 4})]).pipe(delay(3)) ); } @@ -828,35 +794,15 @@ class MockFlightServiceForLoading implements DataService { } private find(from: string, to: string, urgent = false): Observable { - return of([ - { - id: 1, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - ]).pipe(delay(3)); + return of([createFlight({id: 1})]).pipe(delay(3)); } private findById(id: string): Observable { - return of({ - id: 2, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }).pipe(delay(3)); + return of(createFlight({id: 2})).pipe(delay(3)); } private save(flight: Flight): Observable { - return of({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }).pipe(delay(3)); + return of(createFlight({id: 3})).pipe(delay(3)); } private remove(flight: Flight): Observable { @@ -864,14 +810,6 @@ class MockFlightServiceForLoading implements DataService { } } -type Flight = { - id: number; - from: string; - to: string; - date: string; - delayed: boolean; -}; - const Store = signalStore( withCallState(), withEntities(), From f76144ca4d2adb1bf25ffaad3f3e591dde902131 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Sun, 1 Dec 2024 19:08:36 -0600 Subject: [PATCH 10/11] test(dataService): use factory function in tests --- .../src/lib/with-data-service.spec.ts | 378 +++--------------- 1 file changed, 48 insertions(+), 330 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index 2ba3b2e..61cddc5 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -49,13 +49,7 @@ describe('withDataService', () => { tick(); - expect(store.current()).toEqual({ - id: 2, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.current()).toEqual(createFlight({id: 2})); }); })); it('should load by ID from a service and set entities in the store (with named collection)', fakeAsync(() => { @@ -68,13 +62,7 @@ describe('withDataService', () => { tick(); - expect(store.currentFlight()).toEqual({ - id: 2, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.currentFlight()).toEqual(createFlight({id: 2})); }); })); it('should create from a service and set an entity in the store', fakeAsync(() => { @@ -85,23 +73,12 @@ describe('withDataService', () => { expect(store.entities().length).toBe(0); - store.create({ - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - } as Flight); + store.create(createFlight({id: 3})); tick(); expect(store.entities().length).toBe(1); - expect(store.current()).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.current()).toEqual(createFlight({id: 3})); }); })); it('should create from a service and set an entity in the store (with named collection)', fakeAsync(() => { @@ -112,23 +89,12 @@ describe('withDataService', () => { expect(store.flightEntities().length).toBe(0); - store.createFlight({ - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - } as Flight); + store.createFlight(createFlight({id: 3})); tick(); expect(store.flightEntities().length).toBe(1); - expect(store.currentFlight()).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.currentFlight()).toEqual(createFlight({id: 3})); }); })); it('should update from a service and update an entity in the store', fakeAsync(() => { @@ -147,22 +113,10 @@ describe('withDataService', () => { delayed: false, }); tick(); - store.update({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.update(createFlight({id: 3})); tick(); - expect(store.current()).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.current()).toEqual(createFlight({id: 3})); }); })); it('should update from a service and update an entity in the store (with named collection)', fakeAsync(() => { @@ -181,22 +135,10 @@ describe('withDataService', () => { delayed: false, }); tick(); - store.updateFlight({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.updateFlight(createFlight({id: 3})); tick(); - expect(store.currentFlight()).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.currentFlight()).toEqual(createFlight({id: 3})); }); })); it('should update all from a service and update all entities in the store', fakeAsync(() => { @@ -207,53 +149,17 @@ describe('withDataService', () => { expect(store.entities().length).toBe(0); - store.create({ - id: 3, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); - store.create({ - id: 4, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.create(createFlight({id: 3, from: 'Wadena MN'})); + store.create(createFlight({id: 4, from: 'Wadena MN'})); tick(); store.updateAll([ - { - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, + createFlight({id: 3}), + createFlight({id: 4}), ]); tick(); expect(store.entities().length).toBe(2); - expect(store.entities().at(0)).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); - expect(store.entities().at(1)).toEqual({ - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.entities().at(0)).toEqual(createFlight({id: 3})); + expect(store.entities().at(1)).toEqual(createFlight({id: 4})); }); })); it('should update all from a service and update all entities in the store (with named collection)', fakeAsync(() => { @@ -264,53 +170,17 @@ describe('withDataService', () => { expect(store.flightEntities().length).toBe(0); - store.createFlight({ - id: 3, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); - store.createFlight({ - id: 4, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.createFlight(createFlight({id: 3, from: 'Wadena MN'})); + store.createFlight(createFlight({id: 4, from: 'Wadena MN'})); tick(); store.updateAllFlight([ - { - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, + createFlight({id: 3}), + createFlight({id: 4}), ]); tick(); expect(store.flightEntities().length).toBe(2); - expect(store.flightEntities().at(0)).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); - expect(store.flightEntities().at(1)).toEqual({ - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.flightEntities().at(0)).toEqual(createFlight({id: 3})); + expect(store.flightEntities().at(1)).toEqual(createFlight({id: 4})); }); })); it('should delete from a service and update that entity in the store', fakeAsync(() => { @@ -321,29 +191,11 @@ describe('withDataService', () => { expect(store.entities().length).toBe(0); - store.create({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.create(createFlight({id: 3})); tick(); expect(store.entities().length).toBe(1); - expect(store.entities().at(0)).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); - store.delete({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.entities().at(0)).toEqual(createFlight({id: 3})); + store.delete(createFlight({id: 3})); tick(); expect(store.entities().length).toBe(0); }); @@ -356,29 +208,11 @@ describe('withDataService', () => { expect(store.flightEntities().length).toBe(0); - store.createFlight({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.createFlight(createFlight({id: 3})); tick(); expect(store.flightEntities().length).toBe(1); - expect(store.flightEntities().at(0)).toEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); - store.deleteFlight({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.flightEntities().at(0)).toEqual(createFlight({id: 3})); + store.deleteFlight(createFlight({id: 3})); tick(); expect(store.flightEntities().length).toBe(0); }); @@ -389,13 +223,7 @@ describe('withDataService', () => { tick(); - store.create({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.create(createFlight({id: 3})); expect(store.selectedEntities().length).toBe(0); store.updateSelected(3, true); @@ -403,13 +231,7 @@ describe('withDataService', () => { tick(); expect(store.selectedEntities().length).toBe(1); - expect(store.selectedEntities()).toContainEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.selectedEntities()).toContainEqual(createFlight({id: 3})); }); })); it('should update selected flight of the store (with named collection)', fakeAsync(() => { @@ -418,13 +240,7 @@ describe('withDataService', () => { tick(); - store.createFlight({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.createFlight(createFlight({id: 3})); expect(store.selectedFlightEntities().length).toBe(0); store.updateSelectedFlightEntities(3, true); @@ -432,13 +248,7 @@ describe('withDataService', () => { tick(); expect(store.selectedFlightEntities().length).toBe(1); - expect(store.selectedFlightEntities()).toContainEqual({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.selectedFlightEntities()).toContainEqual(createFlight({id: 3})); }); })); it('should update the filter of the service', fakeAsync(() => { @@ -479,28 +289,11 @@ describe('withDataService', () => { const store = new Store(); tick(); - store.create({ - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - } as Flight); + store.create(createFlight({id: 3})); - store.setCurrent({ - id: 4, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.setCurrent(createFlight({id: 4})); - expect(store.current()).toEqual({ - id: 4, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.current()).toEqual(createFlight({id: 4})); }); })); it('set the current entity (with named collection)', fakeAsync(() => { @@ -508,28 +301,11 @@ describe('withDataService', () => { const store = new StoreWithNamedCollection(); tick(); - store.createFlight({ - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - } as Flight); + store.createFlight(createFlight({id: 3})); - store.setCurrentFlight({ - id: 4, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.setCurrentFlight(createFlight({id: 4})); - expect(store.currentFlight()).toEqual({ - id: 4, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + expect(store.currentFlight()).toEqual(createFlight({id: 4})); }); })); @@ -540,12 +316,7 @@ describe('withDataService', () => { expect(store.loading()).toBe(false); - store.create({ - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - } as Flight); + store.create(createFlight({id: 3})); tick(); expect(store.loading()).toBe(true); tick(3); @@ -563,46 +334,22 @@ describe('withDataService', () => { tick(3); expect(store.loading()).toBe(false); - store.update({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.update(createFlight({id: 3})); tick(); expect(store.loading()).toBe(true); tick(3); expect(store.loading()).toBe(false); store.updateAll([ - { - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, + createFlight({id: 3}), + createFlight({id: 4}), ]); tick(); expect(store.loading()).toBe(true); tick(3); expect(store.loading()).toBe(false); - store.delete({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.delete(createFlight({id: 3})); tick(); expect(store.loading()).toBe(true); tick(3); @@ -617,12 +364,7 @@ describe('withDataService', () => { expect(store.flightLoading()).toBe(false); - store.createFlight({ - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - } as Flight); + store.createFlight(createFlight({id: 3})); tick(); expect(store.flightLoading()).toBe(true); tick(3); @@ -640,46 +382,22 @@ describe('withDataService', () => { tick(3); expect(store.flightLoading()).toBe(false); - store.updateFlight({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.updateFlight(createFlight({id: 3})); tick(); expect(store.flightLoading()).toBe(true); tick(3); expect(store.flightLoading()).toBe(false); store.updateAllFlight([ - { - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, - { - id: 4, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }, + createFlight({id: 3}), + createFlight({id: 4}), ]); tick(); expect(store.flightLoading()).toBe(true); tick(3); expect(store.flightLoading()).toBe(false); - store.deleteFlight({ - id: 3, - from: 'Paris', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.deleteFlight(createFlight({id: 3})); tick(); expect(store.flightLoading()).toBe(true); tick(3); From c22557b428d04d88a544c097b8a93de632f9530f Mon Sep 17 00:00:00 2001 From: Michael Small Date: Sun, 1 Dec 2024 19:32:20 -0600 Subject: [PATCH 11/11] test(dataService): pass in actual values to mock service --- .../src/lib/with-data-service.spec.ts | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts index 61cddc5..a058c3d 100644 --- a/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts +++ b/libs/ngrx-toolkit/src/lib/with-data-service.spec.ts @@ -105,13 +105,7 @@ describe('withDataService', () => { expect(store.entities().length).toBe(0); - store.create({ - id: 3, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.create(createFlight({id: 3, from: 'Wadena MN'})); tick(); store.update(createFlight({id: 3})); tick(); @@ -127,13 +121,7 @@ describe('withDataService', () => { expect(store.flightEntities().length).toBe(0); - store.createFlight({ - id: 3, - from: 'Wadena MN', - to: 'New York', - date: new Date().toDateString(), - delayed: false, - }); + store.createFlight(createFlight({id: 3, from: 'Wadena MN'})); tick(); store.updateFlight(createFlight({id: 3})); tick(); @@ -284,7 +272,7 @@ describe('withDataService', () => { }); }); })); - it('should the current entity', fakeAsync(() => { + it('should set the current entity', fakeAsync(() => { TestBed.runInInjectionContext(() => { const store = new Store(); tick(); @@ -296,7 +284,7 @@ describe('withDataService', () => { expect(store.current()).toEqual(createFlight({id: 4})); }); })); - it('set the current entity (with named collection)', fakeAsync(() => { + it('should set the current entity (with named collection)', fakeAsync(() => { TestBed.runInInjectionContext(() => { const store = new StoreWithNamedCollection(); tick(); @@ -439,7 +427,6 @@ class MockFlightService implements DataService { } create(entity: Flight): Promise { - entity.id = 0; return firstValueFrom(this.save(entity)); } @@ -450,7 +437,7 @@ class MockFlightService implements DataService { // eslint-disable-next-line @typescript-eslint/no-unused-vars updateAll(entity: Flight[]): Promise { return firstValueFrom( - of([createFlight({id: 3}), createFlight({id: 4})]) + of(entity) ); } @@ -467,11 +454,11 @@ class MockFlightService implements DataService { } private findById(id: string): Observable { - return of(createFlight({id: 2})); + return of(createFlight({id: Number(id)})); } private save(flight: Flight): Observable { - return of(createFlight({id: 3})); + return of(flight); } private remove(flight: Flight): Observable { @@ -488,7 +475,6 @@ class MockFlightServiceForLoading implements DataService { } create(entity: Flight): Promise { - entity.id = 0; return firstValueFrom(this.save(entity)); } @@ -499,7 +485,7 @@ class MockFlightServiceForLoading implements DataService { // eslint-disable-next-line @typescript-eslint/no-unused-vars updateAll(entity: Flight[]): Promise { return firstValueFrom( - of([createFlight({id: 3}), createFlight({id: 4})]).pipe(delay(3)) + of(entity).pipe(delay(3)) ); } @@ -516,11 +502,11 @@ class MockFlightServiceForLoading implements DataService { } private findById(id: string): Observable { - return of(createFlight({id: 2})).pipe(delay(3)); + return of(createFlight({id: Number(id)})).pipe(delay(3)); } private save(flight: Flight): Observable { - return of(createFlight({id: 3})).pipe(delay(3)); + return of(createFlight(flight)).pipe(delay(3)); } private remove(flight: Flight): Observable {