From 3b6da60bc24794c14ccc4558f366cd954134d890 Mon Sep 17 00:00:00 2001 From: roopkt Date: Sat, 21 Oct 2017 08:40:26 -0400 Subject: [PATCH 1/9] added action action and state sanitizer #494 --- modules/store-devtools/spec/config.spec.ts | 21 +++++++++++++++++++++ modules/store-devtools/src/config.ts | 4 +++- modules/store-devtools/src/instrument.ts | 10 ++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 modules/store-devtools/spec/config.spec.ts diff --git a/modules/store-devtools/spec/config.spec.ts b/modules/store-devtools/spec/config.spec.ts new file mode 100644 index 0000000000..a730dd007f --- /dev/null +++ b/modules/store-devtools/spec/config.spec.ts @@ -0,0 +1,21 @@ +import { ActionReducer, Action } from '@ngrx/store'; +import { StoreDevtoolsConfig } from '../'; + +describe('StoreDevtoolsOptions', () => { + it('can be initialized with actionSanitizer', () => { + const options = new StoreDevtoolsConfig(); + function sanitizer(action: Action, id: number): Action { + return action; + } + options.actionSanitizer = sanitizer; + expect(options.actionSanitizer).toEqual(sanitizer); + }); + it('can be initialized with stateSanitizer', () => { + const options = new StoreDevtoolsConfig(); + function stateSanitizer(state: any, index: number): any { + return state; + } + options.actionSanitizer = stateSanitizer; + expect(options.actionSanitizer).toEqual(stateSanitizer); + }); +}); diff --git a/modules/store-devtools/src/config.ts b/modules/store-devtools/src/config.ts index 7d2a8f7558..d31c2adf8e 100644 --- a/modules/store-devtools/src/config.ts +++ b/modules/store-devtools/src/config.ts @@ -1,9 +1,11 @@ -import { ActionReducer } from '@ngrx/store'; +import { ActionReducer, Action } from '@ngrx/store'; import { InjectionToken, Type } from '@angular/core'; export class StoreDevtoolsConfig { maxAge: number | false; monitor: ActionReducer; + actionSanitizer?: (action: A, id: number) => A; + stateSanitizer?: (state: S, index: number) => S; } export const STORE_DEVTOOLS_CONFIG = new InjectionToken( diff --git a/modules/store-devtools/src/instrument.ts b/modules/store-devtools/src/instrument.ts index 101e77479c..56be93202c 100644 --- a/modules/store-devtools/src/instrument.ts +++ b/modules/store-devtools/src/instrument.ts @@ -64,12 +64,22 @@ export function noMonitor(): null { return null; } +export function noActionSanitizer(): null { + return null; +} + +export function noStateSanitizer(): null { + return null; +} + export function createConfig( _options: StoreDevtoolsOptions ): StoreDevtoolsConfig { const DEFAULT_OPTIONS: StoreDevtoolsConfig = { maxAge: false, monitor: noMonitor, + actionSanitizer: noActionSanitizer, + stateSanitizer: noStateSanitizer, }; let options = typeof _options === 'function' ? _options() : _options; From 22994309568809b5b4c6b35d3d6e6eaecc98aada Mon Sep 17 00:00:00 2001 From: roopkt Date: Fri, 27 Oct 2017 03:06:42 -0400 Subject: [PATCH 2/9] updating the pull request with latest changes #516 --- modules/store-devtools/src/devtools.ts | 6 +++++- modules/store-devtools/src/reducer.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/store-devtools/src/devtools.ts b/modules/store-devtools/src/devtools.ts index e5bf6f7b8d..316a97aa86 100644 --- a/modules/store-devtools/src/devtools.ts +++ b/modules/store-devtools/src/devtools.ts @@ -49,7 +49,11 @@ export class StoreDevtools implements Observer { initialState, liftedInitialState, config.monitor, - config.maxAge ? { maxAge: config.maxAge } : {} + { + maxAge: config.maxAge as number, + actionSanitizer: config.actionSanitizer, + stateSanitizer: config.stateSanitizer, + } ); const liftedAction$ = applyOperators(actions$.asObservable(), [ diff --git a/modules/store-devtools/src/reducer.ts b/modules/store-devtools/src/reducer.ts index 253ee149d8..30e27f586f 100644 --- a/modules/store-devtools/src/reducer.ts +++ b/modules/store-devtools/src/reducer.ts @@ -129,7 +129,11 @@ export function liftReducerWith( initialCommittedState: any, initialLiftedState: LiftedState, monitorReducer?: any, - options: { maxAge?: number } = {} + options: { + maxAge?: number; + actionSanitizer?: (action: A, id: number) => A; + stateSanitizer?: (state: S, index: number) => S; + } = {} ) { /** * Manages how the history actions modify the history state. From 577434ce3f2c3944a0e5d2d976c8288fba3a65c1 Mon Sep 17 00:00:00 2001 From: roopkt Date: Thu, 2 Nov 2017 17:05:46 -0400 Subject: [PATCH 3/9] sending the action/state sanitizers to the redux devtools #516 --- modules/store-devtools/spec/extension.spec.ts | 79 +++++++++++++++++++ modules/store-devtools/src/extension.ts | 18 ++--- modules/store-devtools/src/reducer.ts | 8 +- 3 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 modules/store-devtools/spec/extension.spec.ts diff --git a/modules/store-devtools/spec/extension.spec.ts b/modules/store-devtools/spec/extension.spec.ts new file mode 100644 index 0000000000..f5bb5d1ed6 --- /dev/null +++ b/modules/store-devtools/spec/extension.spec.ts @@ -0,0 +1,79 @@ +import { Action } from '@ngrx/store'; +import { of } from 'rxjs/observable/of'; + +import { LiftedState } from '../'; +import { DevtoolsExtension, ReduxDevtoolsExtension } from '../src/extension'; +import { + createConfig, + noActionSanitizer, + noMonitor, + noStateSanitizer, +} from '../src/instrument'; + +describe('DevtoolsExtension', () => { + let reduxDevtoolsExtension: ReduxDevtoolsExtension; + let devtoolsExtension: DevtoolsExtension; + + beforeEach(() => { + reduxDevtoolsExtension = jasmine.createSpyObj('reduxDevtoolsExtension', [ + 'send', + 'connect', + ]); + (reduxDevtoolsExtension.connect as jasmine.Spy).and.returnValue(of({})); + spyOn(Date, 'now').and.returnValue('1509655064369'); + }); + + describe('notify', () => { + it('should send notification with default options', () => { + devtoolsExtension = new DevtoolsExtension( + reduxDevtoolsExtension, + createConfig({}) + ); + const defaultOptions = { + maxAge: false, + monitor: noMonitor, + actionSanitizer: noActionSanitizer, + stateSanitizer: noStateSanitizer, + }; + const action = {} as Action; + const state = {} as LiftedState; + devtoolsExtension.notify(action, state); + expect(reduxDevtoolsExtension.send).toHaveBeenCalledWith( + null, + {}, + defaultOptions, + 'ngrx-store-1509655064369' + ); + }); + function myActionSanitizer() { + return { type: 'sanitizer' }; + } + function myStateSanitizer() { + return { state: 'new state' }; + } + it('should send notification with given options', () => { + devtoolsExtension = new DevtoolsExtension( + reduxDevtoolsExtension, + createConfig({ + actionSanitizer: myActionSanitizer, + stateSanitizer: myStateSanitizer, + }) + ); + const defaultOptions = { + maxAge: false, + monitor: noMonitor, + actionSanitizer: myActionSanitizer, + stateSanitizer: myStateSanitizer, + }; + const action = {} as Action; + const state = {} as LiftedState; + devtoolsExtension.notify(action, state); + expect(reduxDevtoolsExtension.send).toHaveBeenCalledWith( + null, + {}, + defaultOptions, + 'ngrx-store-1509655064369' + ); + }); + }); +}); diff --git a/modules/store-devtools/src/extension.ts b/modules/store-devtools/src/extension.ts index b98651b328..a3217797ba 100644 --- a/modules/store-devtools/src/extension.ts +++ b/modules/store-devtools/src/extension.ts @@ -1,4 +1,5 @@ -import { InjectionToken, Inject, Injectable } from '@angular/core'; +import { Inject, Injectable, InjectionToken } from '@angular/core'; +import { Action } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; import { empty } from 'rxjs/observable/empty'; import { filter } from 'rxjs/operator/filter'; @@ -6,7 +7,8 @@ import { map } from 'rxjs/operator/map'; import { share } from 'rxjs/operator/share'; import { switchMap } from 'rxjs/operator/switchMap'; import { takeUntil } from 'rxjs/operator/takeUntil'; -import { Action } from '@ngrx/store'; + +import { STORE_DEVTOOLS_CONFIG, StoreDevtoolsConfig } from './config'; import { LiftedState } from './reducer'; import { applyOperators } from './utils'; @@ -35,7 +37,7 @@ export interface ReduxDevtoolsExtension { send( action: any, state: any, - options?: boolean | { serialize: boolean | object }, + options: StoreDevtoolsConfig, instanceId?: string ): void; } @@ -49,7 +51,8 @@ export class DevtoolsExtension { actions$: Observable; constructor( - @Inject(REDUX_DEVTOOLS_EXTENSION) devtoolsExtension: ReduxDevtoolsExtension + @Inject(REDUX_DEVTOOLS_EXTENSION) devtoolsExtension: ReduxDevtoolsExtension, + @Inject(STORE_DEVTOOLS_CONFIG) private config: StoreDevtoolsConfig ) { this.devtoolsExtension = devtoolsExtension; this.createActionStreams(); @@ -60,12 +63,7 @@ export class DevtoolsExtension { return; } - this.devtoolsExtension.send( - null, - state, - { serialize: false }, - this.instanceId - ); + this.devtoolsExtension.send(null, state, this.config, this.instanceId); } private createChangesObservable(): Observable { diff --git a/modules/store-devtools/src/reducer.ts b/modules/store-devtools/src/reducer.ts index 30e27f586f..0bc90b0c9f 100644 --- a/modules/store-devtools/src/reducer.ts +++ b/modules/store-devtools/src/reducer.ts @@ -6,7 +6,7 @@ import { UPDATE, INIT, } from '@ngrx/store'; - +import { StoreDevtoolsConfig } from './config'; import { difference, liftAction } from './utils'; import * as Actions from './actions'; @@ -129,11 +129,7 @@ export function liftReducerWith( initialCommittedState: any, initialLiftedState: LiftedState, monitorReducer?: any, - options: { - maxAge?: number; - actionSanitizer?: (action: A, id: number) => A; - stateSanitizer?: (state: S, index: number) => S; - } = {} + options: Partial = {} ) { /** * Manages how the history actions modify the history state. From 10ddaaa372760be65240568c35adac0d9acc620b Mon Sep 17 00:00:00 2001 From: roopkt Date: Thu, 2 Nov 2017 17:06:35 -0400 Subject: [PATCH 4/9] added tests also # 516 --- modules/router-store/spec/integration.spec.ts | 219 +++++++++--------- 1 file changed, 112 insertions(+), 107 deletions(-) diff --git a/modules/router-store/spec/integration.spec.ts b/modules/router-store/spec/integration.spec.ts index dee373c1db..0aa23ebc9c 100644 --- a/modules/router-store/spec/integration.spec.ts +++ b/modules/router-store/spec/integration.spec.ts @@ -29,7 +29,7 @@ describe('integration spec', () => { } }; - createTestModule({reducers: {reducer}}); + createTestModule({ reducers: { reducer } }); const router: Router = TestBed.get(Router); const store = TestBed.get(Store); @@ -39,18 +39,18 @@ describe('integration spec', () => { .navigateByUrl('/') .then(() => { expect(log).toEqual([ - {type: 'store', state: ''}, // init event. has nothing to do with the router - {type: 'router', event: 'NavigationStart', url: '/'}, - {type: 'router', event: 'RoutesRecognized', url: '/'}, - {type: 'store', state: '/'}, // ROUTER_NAVIGATION event in the store + { type: 'store', state: '' }, // init event. has nothing to do with the router + { type: 'router', event: 'NavigationStart', url: '/' }, + { type: 'router', event: 'RoutesRecognized', url: '/' }, + { type: 'store', state: '/' }, // ROUTER_NAVIGATION event in the store /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/'}, - {type: 'router', event: 'GuardsCheckEnd', url: '/'}, - {type: 'router', event: 'ResolveStart', url: '/'}, - {type: 'router', event: 'ResolveEnd', url: '/'}, + { type: 'router', event: 'GuardsCheckStart', url: '/' }, + { type: 'router', event: 'GuardsCheckEnd', url: '/' }, + { type: 'router', event: 'ResolveStart', url: '/' }, + { type: 'router', event: 'ResolveEnd', url: '/' }, - {type: 'router', event: 'NavigationEnd', url: '/'}, + { type: 'router', event: 'NavigationEnd', url: '/' }, ]); }) .then(() => { @@ -59,17 +59,17 @@ describe('integration spec', () => { }) .then(() => { expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, - {type: 'store', state: '/next'}, + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, + { type: 'store', state: '/next' }, /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/next'}, - {type: 'router', event: 'GuardsCheckEnd', url: '/next'}, - {type: 'router', event: 'ResolveStart', url: '/next'}, - {type: 'router', event: 'ResolveEnd', url: '/next'}, + { type: 'router', event: 'GuardsCheckStart', url: '/next' }, + { type: 'router', event: 'GuardsCheckEnd', url: '/next' }, + { type: 'router', event: 'ResolveStart', url: '/next' }, + { type: 'router', event: 'ResolveEnd', url: '/next' }, - {type: 'router', event: 'NavigationEnd', url: '/next'}, + { type: 'router', event: 'NavigationEnd', url: '/next' }, ]); done(); @@ -88,7 +88,7 @@ describe('integration spec', () => { } }; - createTestModule({reducers: {reducer}}); + createTestModule({ reducers: { reducer } }); const router: Router = TestBed.get(Router); const store = TestBed.get(Store); @@ -103,9 +103,9 @@ describe('integration spec', () => { .catch(e => { expect(e.message).toEqual('You shall not pass!'); expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, - {type: 'router', event: 'NavigationError', url: '/next'}, + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, + { type: 'router', event: 'NavigationError', url: '/next' }, ]); done(); @@ -131,7 +131,7 @@ describe('integration spec', () => { }; createTestModule({ - reducers: {reducer, routerReducer}, + reducers: { reducer, routerReducer }, canActivate: () => false, }); @@ -149,29 +149,28 @@ describe('integration spec', () => { expect(r).toEqual(false); expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, { type: 'store', - state: {url: '/next', lastAction: ROUTER_NAVIGATION}, + state: { url: '/next', lastAction: ROUTER_NAVIGATION }, }, /* new Router Lifecycle in Angular 4.3 - m */ - {type: 'router', event: 'GuardsCheckStart', url: '/next'}, - {type: 'router', event: 'GuardsCheckEnd', url: '/next'}, + { type: 'router', event: 'GuardsCheckStart', url: '/next' }, + { type: 'router', event: 'GuardsCheckEnd', url: '/next' }, // { type: 'router', event: 'ResolveStart', url: '/next' }, // { type: 'router', event: 'ResolveEnd', url: '/next' }, - { type: 'store', state: { url: '/next', lastAction: ROUTER_CANCEL, - storeState: {url: '/next', lastAction: ROUTER_NAVIGATION}, + storeState: { url: '/next', lastAction: ROUTER_NAVIGATION }, }, }, - {type: 'router', event: 'NavigationCancel', url: '/next'}, + { type: 'router', event: 'NavigationCancel', url: '/next' }, ]); done(); @@ -197,7 +196,7 @@ describe('integration spec', () => { }; createTestModule({ - reducers: {reducer, routerReducer}, + reducers: { reducer, routerReducer }, canActivate: () => { throw new Error('BOOM!'); }, @@ -217,40 +216,42 @@ describe('integration spec', () => { expect(e.message).toEqual('BOOM!'); expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, { type: 'store', - state: {url: '/next', lastAction: ROUTER_NAVIGATION}, + state: { url: '/next', lastAction: ROUTER_NAVIGATION }, }, /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/next'}, + { type: 'router', event: 'GuardsCheckStart', url: '/next' }, { type: 'store', state: { url: '/next', lastAction: ROUTER_ERROR, - storeState: {url: '/next', lastAction: ROUTER_NAVIGATION}, + storeState: { url: '/next', lastAction: ROUTER_NAVIGATION }, }, }, - {type: 'router', event: 'NavigationError', url: '/next'}, + { type: 'router', event: 'NavigationError', url: '/next' }, ]); done(); }); }); - it('should call navigateByUrl when resetting state of the routerReducer', (done: any) => { + it('should call navigateByUrl when resetting state of the routerReducer', ( + done: any + ) => { const reducer = (state: any, action: RouterAction) => { const r = routerReducer(state, action); return r && r.state - ? {url: r.state.url, navigationId: r.navigationId} + ? { url: r.state.url, navigationId: r.navigationId } : null; }; - createTestModule({reducers: {routerReducer, reducer}}); + createTestModule({ reducers: { routerReducer, reducer } }); const router = TestBed.get(Router); const store = TestBed.get(Store); @@ -271,17 +272,17 @@ describe('integration spec', () => { }) .then(() => { expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, - {type: 'store', state: {url: '/next', navigationId: 2}}, + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, + { type: 'store', state: { url: '/next', navigationId: 2 } }, /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/next'}, - {type: 'router', event: 'GuardsCheckEnd', url: '/next'}, - {type: 'router', event: 'ResolveStart', url: '/next'}, - {type: 'router', event: 'ResolveEnd', url: '/next'}, + { type: 'router', event: 'GuardsCheckStart', url: '/next' }, + { type: 'router', event: 'GuardsCheckEnd', url: '/next' }, + { type: 'router', event: 'ResolveStart', url: '/next' }, + { type: 'router', event: 'ResolveEnd', url: '/next' }, - {type: 'router', event: 'NavigationEnd', url: '/next'}, + { type: 'router', event: 'NavigationEnd', url: '/next' }, ]); log.splice(0); @@ -289,24 +290,24 @@ describe('integration spec', () => { type: ROUTER_NAVIGATION, payload: { routerState: routerReducerStates[0].state, - event: {id: routerReducerStates[0].navigationId}, + event: { id: routerReducerStates[0].navigationId }, }, }); return waitForNavigation(router); }) .then(() => { expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/'}, - {type: 'store', state: {url: '/', navigationId: 1}}, // restored - {type: 'router', event: 'RoutesRecognized', url: '/'}, + { type: 'router', event: 'NavigationStart', url: '/' }, + { type: 'store', state: { url: '/', navigationId: 1 } }, // restored + { type: 'router', event: 'RoutesRecognized', url: '/' }, /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/'}, - {type: 'router', event: 'GuardsCheckEnd', url: '/'}, - {type: 'router', event: 'ResolveStart', url: '/'}, - {type: 'router', event: 'ResolveEnd', url: '/'}, + { type: 'router', event: 'GuardsCheckStart', url: '/' }, + { type: 'router', event: 'GuardsCheckEnd', url: '/' }, + { type: 'router', event: 'ResolveStart', url: '/' }, + { type: 'router', event: 'ResolveEnd', url: '/' }, - {type: 'router', event: 'NavigationEnd', url: '/'}, + { type: 'router', event: 'NavigationEnd', url: '/' }, ]); log.splice(0); }) @@ -315,39 +316,41 @@ describe('integration spec', () => { type: ROUTER_NAVIGATION, payload: { routerState: routerReducerStates[1].state, - event: {id: routerReducerStates[1].navigationId}, + event: { id: routerReducerStates[1].navigationId }, }, }); return waitForNavigation(router); }) .then(() => { expect(log).toEqual([ - {type: 'store', state: {url: '/next', navigationId: 2}}, // restored - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, + { type: 'store', state: { url: '/next', navigationId: 2 } }, // restored + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/next'}, - {type: 'router', event: 'GuardsCheckEnd', url: '/next'}, - {type: 'router', event: 'ResolveStart', url: '/next'}, - {type: 'router', event: 'ResolveEnd', url: '/next'}, + { type: 'router', event: 'GuardsCheckStart', url: '/next' }, + { type: 'router', event: 'GuardsCheckEnd', url: '/next' }, + { type: 'router', event: 'ResolveStart', url: '/next' }, + { type: 'router', event: 'ResolveEnd', url: '/next' }, - {type: 'router', event: 'NavigationEnd', url: '/next'}, + { type: 'router', event: 'NavigationEnd', url: '/next' }, ]); done(); }); }); - it('should support cancellation of initial navigation using canLoad guard', (done: any) => { + it('should support cancellation of initial navigation using canLoad guard', ( + done: any + ) => { const reducer = (state: any, action: RouterAction) => { const r = routerReducer(state, action); return r && r.state - ? {url: r.state.url, navigationId: r.navigationId} + ? { url: r.state.url, navigationId: r.navigationId } : null; }; createTestModule({ - reducers: {routerReducer, reducer}, + reducers: { routerReducer, reducer }, canLoad: () => false, }); @@ -359,19 +362,21 @@ describe('integration spec', () => { expect(r).toBe(false); expect(log).toEqual([ - {type: 'store', state: null}, - {type: 'router', event: 'NavigationStart', url: '/load'}, - {type: 'store', state: null}, - {type: 'router', event: 'NavigationCancel', url: '/load'}, + { type: 'store', state: null }, + { type: 'router', event: 'NavigationStart', url: '/load' }, + { type: 'store', state: null }, + { type: 'router', event: 'NavigationCancel', url: '/load' }, ]); done(); }); - it('should support a custom RouterStateSnapshot serializer ', (done: any) => { + it('should support a custom RouterStateSnapshot serializer ', ( + done: any + ) => { const reducer = (state: any, action: RouterAction) => { const r = routerReducer(state, action); return r && r.state - ? {url: r.state.url, navigationId: r.navigationId} + ? { url: r.state.url, navigationId: r.navigationId } : null; }; @@ -379,17 +384,17 @@ describe('integration spec', () => { implements RouterStateSerializer<{ url: string; params: any }> { serialize(routerState: RouterStateSnapshot) { const url = `${routerState.url}-custom`; - const params = {test: 1}; + const params = { test: 1 }; - return {url, params}; + return { url, params }; } } const providers = [ - {provide: RouterStateSerializer, useClass: CustomSerializer}, + { provide: RouterStateSerializer, useClass: CustomSerializer }, ]; - createTestModule({reducers: {routerReducer, reducer}, providers}); + createTestModule({ reducers: { routerReducer, reducer }, providers }); const router = TestBed.get(Router); const store = TestBed.get(Store); @@ -403,17 +408,17 @@ describe('integration spec', () => { }) .then(() => { expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, { type: 'store', state: { url: '/next-custom', navigationId: 2, - params: {test: 1}, + params: { test: 1 }, }, }, - {type: 'router', event: 'NavigationEnd', url: '/next'}, + { type: 'router', event: 'NavigationEnd', url: '/next' }, ]); log.splice(0); done(); @@ -423,9 +428,9 @@ describe('integration spec', () => { it('should support event during an async canActivate guard', (done: any) => { createTestModule({ - reducers: {routerReducer}, + reducers: { routerReducer }, canActivate: () => { - store.dispatch({type: 'USER_EVENT'}); + store.dispatch({ type: 'USER_EVENT' }); return store.take(1).mapTo(true); }, }); @@ -442,18 +447,18 @@ describe('integration spec', () => { }) .then(() => { expect(log).toEqual([ - {type: 'router', event: 'NavigationStart', url: '/next'}, - {type: 'router', event: 'RoutesRecognized', url: '/next'}, - {type: 'store', state: undefined}, // after ROUTER_NAVIGATION + { type: 'router', event: 'NavigationStart', url: '/next' }, + { type: 'router', event: 'RoutesRecognized', url: '/next' }, + { type: 'store', state: undefined }, // after ROUTER_NAVIGATION /* new Router Lifecycle in Angular 4.3 */ - {type: 'router', event: 'GuardsCheckStart', url: '/next'}, - {type: 'store', state: undefined}, // after USER_EVENT - {type: 'router', event: 'GuardsCheckEnd', url: '/next'}, - {type: 'router', event: 'ResolveStart', url: '/next'}, - {type: 'router', event: 'ResolveEnd', url: '/next'}, + { type: 'router', event: 'GuardsCheckStart', url: '/next' }, + { type: 'store', state: undefined }, // after USER_EVENT + { type: 'router', event: 'GuardsCheckEnd', url: '/next' }, + { type: 'router', event: 'ResolveStart', url: '/next' }, + { type: 'router', event: 'ResolveEnd', url: '/next' }, - {type: 'router', event: 'NavigationEnd', url: '/next'}, + { type: 'router', event: 'NavigationEnd', url: '/next' }, ]); done(); @@ -461,32 +466,32 @@ describe('integration spec', () => { }); }); -function createTestModule(opts: { - reducers?: any; - canActivate?: Function; - canLoad?: Function; - providers?: Provider[]; -} = {}) { +function createTestModule( + opts: { + reducers?: any; + canActivate?: Function; + canLoad?: Function; + providers?: Provider[]; + } = {} +) { @Component({ selector: 'test-app', template: '', }) - class AppCmp { - } + class AppCmp {} @Component({ selector: 'pagea-cmp', template: 'pagea-cmp', }) - class SimpleCmp { - } + class SimpleCmp {} TestBed.configureTestingModule({ declarations: [AppCmp, SimpleCmp], imports: [ StoreModule.forRoot(opts.reducers), RouterTestingModule.withRoutes([ - {path: '', component: SimpleCmp}, + { path: '', component: SimpleCmp }, { path: 'next', component: SimpleCmp, @@ -532,6 +537,6 @@ function logOfRouterAndStore(router: Router, store: Store): any[] { url: (e).url.toString(), }) ); - store.subscribe(store => log.push({type: 'store', state: store.reducer})); + store.subscribe(store => log.push({ type: 'store', state: store.reducer })); return log; } From b08fc952c23972572a8c2af6aca7f6f72b367723 Mon Sep 17 00:00:00 2001 From: roopkt Date: Mon, 13 Nov 2017 12:39:02 -0500 Subject: [PATCH 5/9] fixing the merging issue #544 --- modules/store-devtools/spec/config.spec.ts | 5 +++++ modules/store-devtools/spec/extension.spec.ts | 5 +++++ modules/store-devtools/src/config.ts | 2 ++ modules/store-devtools/src/devtools.ts | 6 +----- modules/store-devtools/src/instrument.ts | 4 ++++ 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/modules/store-devtools/spec/config.spec.ts b/modules/store-devtools/spec/config.spec.ts index a730dd007f..8af6116ed5 100644 --- a/modules/store-devtools/spec/config.spec.ts +++ b/modules/store-devtools/spec/config.spec.ts @@ -2,6 +2,11 @@ import { ActionReducer, Action } from '@ngrx/store'; import { StoreDevtoolsConfig } from '../'; describe('StoreDevtoolsOptions', () => { + it('can be initialized with name', () => { + const options = new StoreDevtoolsConfig(); + options.name = 'my instance'; + expect(options.name).toBe('my instance'); + }); it('can be initialized with actionSanitizer', () => { const options = new StoreDevtoolsConfig(); function sanitizer(action: Action, id: number): Action { diff --git a/modules/store-devtools/spec/extension.spec.ts b/modules/store-devtools/spec/extension.spec.ts index f5bb5d1ed6..3a4fee79bd 100644 --- a/modules/store-devtools/spec/extension.spec.ts +++ b/modules/store-devtools/spec/extension.spec.ts @@ -34,6 +34,8 @@ describe('DevtoolsExtension', () => { monitor: noMonitor, actionSanitizer: noActionSanitizer, stateSanitizer: noStateSanitizer, + name: 'NgRx Store DevTools', + serialize: false, }; const action = {} as Action; const state = {} as LiftedState; @@ -57,6 +59,7 @@ describe('DevtoolsExtension', () => { createConfig({ actionSanitizer: myActionSanitizer, stateSanitizer: myStateSanitizer, + name: 'ngrx-store-devtool-todolist', }) ); const defaultOptions = { @@ -64,6 +67,8 @@ describe('DevtoolsExtension', () => { monitor: noMonitor, actionSanitizer: myActionSanitizer, stateSanitizer: myStateSanitizer, + name: 'ngrx-store-devtool-todolist', + serialize: false, }; const action = {} as Action; const state = {} as LiftedState; diff --git a/modules/store-devtools/src/config.ts b/modules/store-devtools/src/config.ts index d31c2adf8e..e15e29d367 100644 --- a/modules/store-devtools/src/config.ts +++ b/modules/store-devtools/src/config.ts @@ -6,6 +6,8 @@ export class StoreDevtoolsConfig { monitor: ActionReducer; actionSanitizer?: (action: A, id: number) => A; stateSanitizer?: (state: S, index: number) => S; + name?: string; + serialize?: boolean; } export const STORE_DEVTOOLS_CONFIG = new InjectionToken( diff --git a/modules/store-devtools/src/devtools.ts b/modules/store-devtools/src/devtools.ts index 316a97aa86..2a8df0f888 100644 --- a/modules/store-devtools/src/devtools.ts +++ b/modules/store-devtools/src/devtools.ts @@ -49,11 +49,7 @@ export class StoreDevtools implements Observer { initialState, liftedInitialState, config.monitor, - { - maxAge: config.maxAge as number, - actionSanitizer: config.actionSanitizer, - stateSanitizer: config.stateSanitizer, - } + config ); const liftedAction$ = applyOperators(actions$.asObservable(), [ diff --git a/modules/store-devtools/src/instrument.ts b/modules/store-devtools/src/instrument.ts index 56be93202c..8d77e87674 100644 --- a/modules/store-devtools/src/instrument.ts +++ b/modules/store-devtools/src/instrument.ts @@ -56,6 +56,8 @@ export function createReduxDevtoolsExtension() { } } +export const DEFAULT_NAME = 'NgRx Store DevTools'; + export function createStateObservable(devtools: StoreDevtools) { return devtools.state; } @@ -80,6 +82,8 @@ export function createConfig( monitor: noMonitor, actionSanitizer: noActionSanitizer, stateSanitizer: noStateSanitizer, + name: DEFAULT_NAME, + serialize: false, }; let options = typeof _options === 'function' ? _options() : _options; From 2ba38f4dcaaecae73190ca0ce3038728e5ee214f Mon Sep 17 00:00:00 2001 From: roopkt Date: Mon, 13 Nov 2017 16:36:23 -0500 Subject: [PATCH 6/9] fixing merge issue #544 --- modules/store-devtools/spec/extension.spec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/store-devtools/spec/extension.spec.ts b/modules/store-devtools/spec/extension.spec.ts index 51c5260263..626490dffe 100644 --- a/modules/store-devtools/spec/extension.spec.ts +++ b/modules/store-devtools/spec/extension.spec.ts @@ -3,7 +3,12 @@ import { of } from 'rxjs/observable/of'; import { LiftedState } from '../'; import { DevtoolsExtension, ReduxDevtoolsExtension } from '../src/extension'; -import { createConfig, noActionSanitizer, noMonitor, noStateSanitizer } from '../src/instrument'; +import { + createConfig, + noActionSanitizer, + noMonitor, + noStateSanitizer, +} from '../src/instrument'; describe('DevtoolsExtension', () => { let reduxDevtoolsExtension: ReduxDevtoolsExtension; From 0906638f621416c55fe17ea5edfa61e54f0d01a4 Mon Sep 17 00:00:00 2001 From: roopkt Date: Mon, 13 Nov 2017 16:36:35 -0500 Subject: [PATCH 7/9] fixing merge issue #544 --- modules/router-store/spec/integration.spec.ts | 2 +- modules/store-devtools/spec/config.spec.ts | 3 +-- modules/store-devtools/src/instrument.ts | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/router-store/spec/integration.spec.ts b/modules/router-store/spec/integration.spec.ts index a8826bfdce..f577e9365c 100644 --- a/modules/router-store/spec/integration.spec.ts +++ b/modules/router-store/spec/integration.spec.ts @@ -590,4 +590,4 @@ function logOfRouterAndStore(router: Router, store: Store): any[] { ); store.subscribe(store => log.push({ type: 'store', state: store.reducer })); return log; -} \ No newline at end of file +} diff --git a/modules/store-devtools/spec/config.spec.ts b/modules/store-devtools/spec/config.spec.ts index 92b7314015..4e1b8c5378 100644 --- a/modules/store-devtools/spec/config.spec.ts +++ b/modules/store-devtools/spec/config.spec.ts @@ -7,7 +7,7 @@ describe('StoreDevtoolsOptions', () => { options.name = 'my instance'; expect(options.name).toBe('my instance'); }); - + it('can be initialized with actionSanitizer', () => { const options = new StoreDevtoolsConfig(); function sanitizer(action: Action, id: number): Action { @@ -24,5 +24,4 @@ describe('StoreDevtoolsOptions', () => { options.actionSanitizer = stateSanitizer; expect(options.actionSanitizer).toEqual(stateSanitizer); }); - }); diff --git a/modules/store-devtools/src/instrument.ts b/modules/store-devtools/src/instrument.ts index 0e4bd37e39..6dd0690373 100644 --- a/modules/store-devtools/src/instrument.ts +++ b/modules/store-devtools/src/instrument.ts @@ -66,7 +66,6 @@ export function noMonitor(): null { return null; } - export function noActionSanitizer(): null { return null; } @@ -77,7 +76,6 @@ export function noStateSanitizer(): null { export const DEFAULT_NAME = 'NgRx Store DevTools'; - export function createConfig( _options: StoreDevtoolsOptions ): StoreDevtoolsConfig { From 07c72cace6b38e96833c4f986182452c4c28fbf7 Mon Sep 17 00:00:00 2001 From: roopkt Date: Tue, 14 Nov 2017 09:42:57 -0500 Subject: [PATCH 8/9] trying to resolve merge issues #544 --- modules/store-devtools/src/instrument.ts | 2 -- modules/store-devtools/src/reducer.ts | 1 - 2 files changed, 3 deletions(-) diff --git a/modules/store-devtools/src/instrument.ts b/modules/store-devtools/src/instrument.ts index 6dd0690373..3353ac47e2 100644 --- a/modules/store-devtools/src/instrument.ts +++ b/modules/store-devtools/src/instrument.ts @@ -56,8 +56,6 @@ export function createReduxDevtoolsExtension() { } } -export const DEFAULT_NAME = 'NgRx Store DevTools'; - export function createStateObservable(devtools: StoreDevtools) { return devtools.state; } diff --git a/modules/store-devtools/src/reducer.ts b/modules/store-devtools/src/reducer.ts index 5624d4544b..116737b61a 100644 --- a/modules/store-devtools/src/reducer.ts +++ b/modules/store-devtools/src/reducer.ts @@ -6,7 +6,6 @@ import { UPDATE, INIT, } from '@ngrx/store'; -import { StoreDevtoolsConfig } from './config'; import { difference, liftAction } from './utils'; import * as Actions from './actions'; import { StoreDevtoolsConfig } from './config'; From c49bdb8c53e8c0b80c89929be4e832dbf013b828 Mon Sep 17 00:00:00 2001 From: roopkt Date: Tue, 14 Nov 2017 12:46:34 -0500 Subject: [PATCH 9/9] fixed code review #544 --- modules/store-devtools/spec/config.spec.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/store-devtools/spec/config.spec.ts b/modules/store-devtools/spec/config.spec.ts index 4e1b8c5378..2c5ae5ee7b 100644 --- a/modules/store-devtools/spec/config.spec.ts +++ b/modules/store-devtools/spec/config.spec.ts @@ -16,12 +16,13 @@ describe('StoreDevtoolsOptions', () => { options.actionSanitizer = sanitizer; expect(options.actionSanitizer).toEqual(sanitizer); }); + it('can be initialized with stateSanitizer', () => { const options = new StoreDevtoolsConfig(); function stateSanitizer(state: any, index: number): any { return state; } - options.actionSanitizer = stateSanitizer; - expect(options.actionSanitizer).toEqual(stateSanitizer); + options.stateSanitizer = stateSanitizer; + expect(options.stateSanitizer).toEqual(stateSanitizer); }); });