Skip to content

Commit

Permalink
allow configuration of createSerializableStateInvariantMiddleware ign…
Browse files Browse the repository at this point in the history
…oredActionPaths, update default value, add tests (#457)
  • Loading branch information
phryneas committed Apr 4, 2020
1 parent 828026d commit 55253e8
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 25 deletions.
1 change: 1 addition & 0 deletions etc/redux-toolkit.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ export { Selector }
// @public
export interface SerializableStateInvariantMiddlewareOptions {
getEntries?: (value: any) => [string, any][];
ignoredActionPaths?: string[];
ignoredActions?: string[];
ignoredPaths?: string[];
isSerializable?: (value: any) => boolean;
Expand Down
13 changes: 13 additions & 0 deletions src/createAsyncThunk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,16 @@ describe('createAsyncThunk with abortController', () => {
})
})
})

test('non-serializable arguments are ignored by serializableStateInvariantMiddleware', async () => {
const restore = mockConsole(createConsole())
const nonSerializableValue = new Map()
const asyncThunk = createAsyncThunk('test', (arg: Map<any, any>) => {})

configureStore({
reducer: () => 0
}).dispatch(asyncThunk(nonSerializableValue))

expect(getLog().log).toMatchInlineSnapshot(`""`)
restore()
})
78 changes: 55 additions & 23 deletions src/serializableStateInvariantMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,61 @@ describe('serializableStateInvariantMiddleware', () => {
expect(numTimesCalled).toBeGreaterThan(0)
})

describe('ignored action paths', () => {
function reducer() {
return 0
}
const nonSerializableValue = new Map()

it('default value: meta.arg', () => {
configureStore({
reducer,
middleware: [createSerializableStateInvariantMiddleware()]
}).dispatch({ type: 'test', meta: { arg: nonSerializableValue } })

expect(getLog().log).toMatchInlineSnapshot(`""`)
})

it('default value can be overridden', () => {
configureStore({
reducer,
middleware: [
createSerializableStateInvariantMiddleware({
ignoredActionPaths: []
})
]
}).dispatch({ type: 'test', meta: { arg: nonSerializableValue } })

expect(getLog().log).toMatchInlineSnapshot(`
"A non-serializable value was detected in an action, in the path: \`meta.arg\`. Value: Map {}
Take a look at the logic that dispatched this action: Object {
\\"meta\\": Object {
\\"arg\\": Map {},
},
\\"type\\": \\"test\\",
}
(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)"
`)
})

it('can specify (multiple) different values', () => {
configureStore({
reducer,
middleware: [
createSerializableStateInvariantMiddleware({
ignoredActionPaths: ['payload', 'meta.arg']
})
]
}).dispatch({
type: 'test',
payload: { arg: nonSerializableValue },
meta: { arg: nonSerializableValue }
})

expect(getLog().log).toMatchInlineSnapshot(`""`)
})
})

it('should not check serializability for ignored slice names', () => {
const ACTION_TYPE = 'TEST_ACTION'

Expand Down Expand Up @@ -386,29 +441,6 @@ describe('serializableStateInvariantMiddleware', () => {
`)
})

it('should not check serializability for meta.args by default', () => {
const badValue = new Map()

const reducer: Reducer = (state = 42, action) => {
return state
}

const serializableStateInvariantMiddleware = createSerializableStateInvariantMiddleware()

const store = configureStore({
reducer: {
testSlice: reducer
},
middleware: [serializableStateInvariantMiddleware]
})

store.dispatch({ type: 'testAction', meta: { args: { badValue } } })

const { log } = getLog()
expect(log).toBe('')
const q = 42
})

it('Should print a warning if execution takes too long', () => {
const reducer: Reducer = (state = 42, action) => {
return state
Expand Down
11 changes: 9 additions & 2 deletions src/serializableStateInvariantMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function findNonSerializableValue(
path: ReadonlyArray<string> = [],
isSerializable: (value: unknown) => boolean = isPlain,
getEntries?: (value: unknown) => [string, any][],
ignoredPaths: string[] = ['meta.args']
ignoredPaths: string[] = []
): NonSerializableValue | false {
let foundNestedSerializable: NonSerializableValue | false

Expand Down Expand Up @@ -111,6 +111,11 @@ export interface SerializableStateInvariantMiddlewareOptions {
*/
ignoredActions?: string[]

/**
* An array of dot-separated path strings to ignore when checking for serializability, Defaults to ['meta.arg']
*/
ignoredActionPaths?: string[]

/**
* An array of dot-separated path strings to ignore when checking for serializability, Defaults to []
*/
Expand Down Expand Up @@ -140,6 +145,7 @@ export function createSerializableStateInvariantMiddleware(
isSerializable = isPlain,
getEntries,
ignoredActions = [],
ignoredActionPaths = ['meta.arg'],
ignoredPaths = [],
warnAfter = 32
} = options
Expand All @@ -158,7 +164,8 @@ export function createSerializableStateInvariantMiddleware(
action,
[],
isSerializable,
getEntries
getEntries,
ignoredActionPaths
)

if (foundActionNonSerializableValue) {
Expand Down

0 comments on commit 55253e8

Please sign in to comment.