Skip to content

Commit

Permalink
feat(store): ignore actions from NgRx libraries in runtime checks (#2351
Browse files Browse the repository at this point in the history
)
  • Loading branch information
timdeschryver authored Feb 6, 2020
1 parent 381f98e commit 0dabfc4
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 22 deletions.
8 changes: 4 additions & 4 deletions modules/store/spec/meta-reducers/immutability_reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ describe('immutabilityCheckMetaReducer:', () => {

function invokeActionReducer(reduce: Function, checkIsOn = true) {
immutabilityCheckMetaReducer((state, action) => reduce(state, action), {
action: checkIsOn,
state: false,
action: () => checkIsOn,
state: () => false,
})({}, { type: 'invoke', numbers: [1, 2, 3], fun: function() {} });
}
});
Expand Down Expand Up @@ -95,8 +95,8 @@ describe('immutabilityCheckMetaReducer:', () => {
return reduce(state, action);
},
{
state: checkIsOn,
action: false,
state: () => checkIsOn,
action: () => false,
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ describe('serializationCheckMetaReducer:', () => {

function invokeActionReducer(action: any, checkIsOn = true) {
serializationCheckMetaReducer(state => state, {
action: checkIsOn,
state: false,
action: () => checkIsOn,
state: () => false,
})(undefined, action);
}

function invokeStateReducer(nextState?: any, checkIsOn = true) {
serializationCheckMetaReducer(() => nextState, {
state: checkIsOn,
action: false,
state: () => checkIsOn,
action: () => false,
})(undefined, {
type: 'invokeReducer',
});
Expand Down
31 changes: 30 additions & 1 deletion modules/store/spec/runtime_checks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as ngCore from '@angular/core';
import { TestBed, fakeAsync, flush } from '@angular/core/testing';
import { Store, StoreModule, META_REDUCERS, USER_RUNTIME_CHECKS } from '..';
import { createActiveRuntimeChecks } from '../src/runtime_checks';
import { RuntimeChecks } from '../src/models';
import { RuntimeChecks, Action } from '../src/models';
import * as metaReducers from '../src/meta-reducers';

describe('Runtime checks:', () => {
Expand Down Expand Up @@ -203,6 +203,18 @@ describe('Runtime checks:', () => {
}).not.toThrow();
})
);

it(
'should not throw for NgRx actions',
fakeAsync(() => {
const store = setupStore({ strictStateSerializability: true });

expect(() => {
store.dispatch(makeNgrxAction(invalidAction()));
flush();
}).not.toThrow();
})
);
});

describe('Action Serialization:', () => {
Expand Down Expand Up @@ -295,6 +307,18 @@ describe('Runtime checks:', () => {
}).not.toThrow();
})
);

it(
'should not throw for NgRx actions',
fakeAsync(() => {
const store = setupStore({ strictActionImmutability: true });

expect(() => {
store.dispatch(makeNgrxAction(invalidAction()));
flush();
}).not.toThrow();
})
);
});
});

Expand Down Expand Up @@ -350,3 +374,8 @@ function reducerWithBugs(state: any = {}, action: any) {
return state;
}
}

export function makeNgrxAction(action: Action) {
action.type = '@ngrx ' + action.type;
return action;
}
8 changes: 4 additions & 4 deletions modules/store/src/meta-reducers/immutability_reducer.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { ActionReducer } from '../models';
import { ActionReducer, Action } from '../models';
import { isFunction, hasOwnProperty, isObjectLike } from './utils';

export function immutabilityCheckMetaReducer(
reducer: ActionReducer<any, any>,
checks: { action: boolean; state: boolean }
checks: { action: (action: Action) => boolean; state: () => boolean }
): ActionReducer<any, any> {
return function(state, action) {
const act = checks.action ? freeze(action) : action;
const act = checks.action(action) ? freeze(action) : action;

const nextState = reducer(state, act);

return checks.state ? freeze(nextState) : nextState;
return checks.state() ? freeze(nextState) : nextState;
};
}

Expand Down
8 changes: 4 additions & 4 deletions modules/store/src/meta-reducers/serialization_reducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ActionReducer } from '../models';
import { ActionReducer, Action } from '../models';
import {
isPlainObject,
isUndefined,
Expand All @@ -11,17 +11,17 @@ import {

export function serializationCheckMetaReducer(
reducer: ActionReducer<any, any>,
checks: { action: boolean; state: boolean }
checks: { action: (action: Action) => boolean; state: () => boolean }
): ActionReducer<any, any> {
return function(state, action) {
if (checks.action) {
if (checks.action(action)) {
const unserializableAction = getUnserializable(action);
throwIfUnserializable(unserializableAction, 'action');
}

const nextState = reducer(state, action);

if (checks.state) {
if (checks.state()) {
const unserializableState = getUnserializable(nextState);
throwIfUnserializable(unserializableState, 'state');
}
Expand Down
16 changes: 11 additions & 5 deletions modules/store/src/runtime_checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
serializationCheckMetaReducer,
immutabilityCheckMetaReducer,
} from './meta-reducers';
import { RuntimeChecks, MetaReducer } from './models';
import { RuntimeChecks, MetaReducer, Action } from './models';
import {
_USER_RUNTIME_CHECKS,
_ACTIVE_RUNTIME_CHECKS,
Expand Down Expand Up @@ -39,8 +39,9 @@ export function createSerializationCheckMetaReducer({
return reducer =>
strictActionSerializability || strictStateSerializability
? serializationCheckMetaReducer(reducer, {
action: strictActionSerializability,
state: strictStateSerializability,
action: action =>
strictActionSerializability && !ignoreNgrxAction(action),
state: () => strictStateSerializability,
})
: reducer;
}
Expand All @@ -52,12 +53,17 @@ export function createImmutabilityCheckMetaReducer({
return reducer =>
strictActionImmutability || strictStateImmutability
? immutabilityCheckMetaReducer(reducer, {
action: strictActionImmutability,
state: strictStateImmutability,
action: action =>
strictActionImmutability && !ignoreNgrxAction(action),
state: () => strictStateImmutability,
})
: reducer;
}

function ignoreNgrxAction(action: Action) {
return action.type.startsWith('@ngrx');
}

export function provideRuntimeChecks(
runtimeChecks?: Partial<RuntimeChecks>
): Provider[] {
Expand Down

0 comments on commit 0dabfc4

Please sign in to comment.