UNPKG

@ngxs/store

Version:
286 lines (277 loc) 10.6 kB
import { TestBed } from '@angular/core/testing'; import { ɵgetDOM as _getDOM, BrowserModule, ɵBrowserDomAdapter as _BrowserDomAdapter } from '@angular/platform-browser'; import * as i0 from '@angular/core'; import { DOCUMENT, destroyPlatform, VERSION, createPlatform, Injector, Component, NgModule, ApplicationRef, provideEnvironmentInitializer, inject, DestroyRef, Injectable } from '@angular/core'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; import { NgxsModule, Store, Actions, ActionStatus } from '@ngxs/store'; import { ReplaySubject, Subject, takeUntil } from 'rxjs'; function createRootElement() { const document = TestBed.inject(DOCUMENT); const root = _getDOM().createElement('app-root', document); document.body.appendChild(root); } function removeRootElement() { const root = document.getElementsByTagName('app-root').item(0); try { document.body.removeChild(root); } catch { } } function destroyPlatformBeforeBootstrappingTheNewOne(freshUrl) { destroyPlatform(); resetLocationToUrl(freshUrl); createRootElement(); } // As we create our custom platform via `bootstrapModule` // we have to destroy it after assetions and revert // the previous one function resetPlatformAfterBootstrapping() { removeRootElement(); destroyPlatform(); const version = +VERSION.major; // https://github.com/angular/angular/commit/e250db4f261741b04ee4cbad4dec41a8908a12aa if (version < 14) { createPlatform(TestBed.inject(Injector)); } } function resetLocationToUrl(freshUrl) { window.history.replaceState({}, 'Test', freshUrl); } function freshPlatform(fn) { let resolve = null; let reject = null; let whenDoneIsCalledPromise = null; const hasDoneArgument = fn.length === 1; if (hasDoneArgument) { whenDoneIsCalledPromise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; }); } return async function testWithAFreshPlatform() { try { const freshUrl = '/'; destroyPlatformBeforeBootstrappingTheNewOne(freshUrl); if (hasDoneArgument) { await fn((error) => { if (error) { reject(error); } else { resolve(); } }); await whenDoneIsCalledPromise; } else { await fn(); } } finally { resetPlatformAfterBootstrapping(); } }; } class NgxsTestComponent { ngOnInit() { } ngAfterViewInit() { } /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsTestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.3", type: NgxsTestComponent, isStandalone: true, selector: "app-root", ngImport: i0, template: '', isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsTestComponent, decorators: [{ type: Component, args: [{ selector: 'app-root', template: '' }] }] }); class NgxsTestModule { static ngDoBootstrap(app) { app.bootstrap(NgxsTestComponent); } /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsTestModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); /** @nocollapse */ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: NgxsTestModule, imports: [BrowserModule, NgxsTestComponent] }); /** @nocollapse */ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsTestModule, imports: [BrowserModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsTestModule, decorators: [{ type: NgModule, args: [{ imports: [BrowserModule, NgxsTestComponent] }] }] }); function loggedError(message) { return ['error', [expect.objectContaining({ message })]]; } function skipConsoleLogging(fn, consoleRecorder = []) { const consoleSpies = [ jest.spyOn(console, 'log').mockImplementation((...args) => { consoleRecorder.push(['log', args]); }), jest.spyOn(console, 'warn').mockImplementation((...args) => { consoleRecorder.push(['warn', args]); }), jest.spyOn(console, 'error').mockImplementation((...args) => { consoleRecorder.push(['error', args]); }), jest.spyOn(console, 'info').mockImplementation((...args) => { consoleRecorder.push(['info', args]); }) ]; function restoreSpies() { consoleSpies.forEach(spy => spy.mockRestore()); } let restoreSpyAsync = false; try { const returnValue = fn(); if (returnValue instanceof Promise) { restoreSpyAsync = true; return returnValue.finally(() => restoreSpies()); } return returnValue; } finally { if (!restoreSpyAsync) { restoreSpies(); } } } class NgxsTestBed { static configureTestingStates(options) { this.resetTestBed(); if (options.before) { options.before(); } skipConsoleLogging(() => TestBed.configureTestingModule({ imports: [ NgxsTestModule, NgxsModule.forRoot(options.states || [], options.ngxsOptions || {}), ...(options.imports || []) ] }).compileComponents()); NgxsTestBed.ngxsBootstrap(); return { get store() { return TestBed.inject(Store); }, get getTestBed() { return TestBed; } }; } static ngxsBootstrap() { NgxsTestBed.createRootNode(); NgxsTestModule.ngDoBootstrap(TestBed.inject(ApplicationRef)); } static resetTestBed() { TestBed.resetTestEnvironment(); TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: true } }); } static createRootNode(selector = 'app-root') { const document = TestBed.inject(DOCUMENT); const adapter = new _BrowserDomAdapter(); const root = adapter.createElement(selector); document.body.appendChild(root); } } class NgxsActionCollector { /** * Including this in your providers will * set up the the action collector to start collecting actions * from before NGXS initializes * @example * // In your providers declaration for your tests: * { * providers: [ * NgxsActionCollector.collectActions(), * provideStore([MyState]), * ], * // ... * } * // and then in your test: * const actionCollector = TestBed.inject(NgxsActionCollector); * const actionsDispatched = actionCollector.dispatched; * const action = actionsDispatched.find( * (item) => item instanceof MyAction * ); * expect(action).toBeDefined(); * @returns An environment initializer that starts the collector immediately */ static collectActions() { return provideEnvironmentInitializer(() => { inject(NgxsActionCollector).start(); }); } _destroyed$ = new ReplaySubject(1); _stopped$ = new Subject(); _started = false; dispatched = []; completed = []; successful = []; errored = []; cancelled = []; _actions$ = inject(Actions); constructor() { inject(DestroyRef).onDestroy(() => this._destroyed$.next()); } start() { if (this._started) { return; } this._started = true; this._actions$.pipe(takeUntil(this._destroyed$), takeUntil(this._stopped$)).subscribe({ next: (ctx) => { switch (ctx?.status) { case ActionStatus.Dispatched: this.dispatched.push(ctx.action); break; case ActionStatus.Successful: this.successful.push(ctx.action); this.completed.push(ctx.action); break; case ActionStatus.Errored: this.errored.push(ctx.action); this.completed.push(ctx.action); break; case ActionStatus.Canceled: this.cancelled.push(ctx.action); this.completed.push(ctx.action); break; default: break; } }, complete: () => { this._started = false; }, error: () => { this._started = false; } }); } reset() { function clearArray(array) { array.splice(0, array.length); } clearArray(this.dispatched); clearArray(this.completed); clearArray(this.successful); clearArray(this.errored); clearArray(this.cancelled); } stop() { this._stopped$.next(); } /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsActionCollector, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsActionCollector, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxsActionCollector, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); /** * Generated bundle index. Do not edit. */ export { NgxsActionCollector, NgxsTestBed, freshPlatform, loggedError, skipConsoleLogging }; //# sourceMappingURL=ngxs-store-internals-testing.mjs.map