gs-port / node_modules /@reduxjs /toolkit /src /tests /createAction.test-d.tsx
Scribbler310's picture
feat: enhance dashboard
c2b7eb3 verified
import type {
Action,
ActionCreator,
ActionCreatorWithNonInferrablePayload,
ActionCreatorWithOptionalPayload,
ActionCreatorWithPayload,
ActionCreatorWithPreparedPayload,
ActionCreatorWithoutPayload,
PayloadAction,
PayloadActionCreator,
UnknownAction,
} from '@reduxjs/toolkit'
import { createAction } from '@reduxjs/toolkit'
describe('type tests', () => {
describe('PayloadAction', () => {
test('PayloadAction has type parameter for the payload.', () => {
const action: PayloadAction<number> = { type: '', payload: 5 }
expectTypeOf(action.payload).toBeNumber()
expectTypeOf(action.payload).not.toBeString()
})
test('PayloadAction type parameter is required.', () => {
expectTypeOf({ type: '', payload: 5 }).not.toMatchTypeOf<PayloadAction>()
})
test('PayloadAction has a string type tag.', () => {
expectTypeOf({ type: '', payload: 5 }).toEqualTypeOf<
PayloadAction<number>
>()
expectTypeOf({ type: 1, payload: 5 }).not.toMatchTypeOf<PayloadAction>()
})
test('PayloadAction is compatible with Action<string>', () => {
const action: PayloadAction<number> = { type: '', payload: 5 }
expectTypeOf(action).toMatchTypeOf<Action<string>>()
})
})
describe('PayloadActionCreator', () => {
test('PayloadActionCreator returns correctly typed PayloadAction depending on whether a payload is passed.', () => {
const actionCreator = Object.assign(
(payload?: number) => ({
type: 'action',
payload,
}),
{ type: 'action' },
) as PayloadActionCreator<number | undefined>
expectTypeOf(actionCreator(1)).toEqualTypeOf<
PayloadAction<number | undefined>
>()
expectTypeOf(actionCreator()).toEqualTypeOf<
PayloadAction<number | undefined>
>()
expectTypeOf(actionCreator(undefined)).toEqualTypeOf<
PayloadAction<number | undefined>
>()
expectTypeOf(actionCreator()).not.toMatchTypeOf<PayloadAction<number>>()
expectTypeOf(actionCreator(1)).not.toMatchTypeOf<
PayloadAction<undefined>
>()
})
test('PayloadActionCreator is compatible with ActionCreator.', () => {
const payloadActionCreator = Object.assign(
(payload?: number) => ({
type: 'action',
payload,
}),
{ type: 'action' },
) as PayloadActionCreator
expectTypeOf(payloadActionCreator).toMatchTypeOf<
ActionCreator<UnknownAction>
>()
const payloadActionCreator2 = Object.assign(
(payload?: number) => ({
type: 'action',
payload: payload || 1,
}),
{ type: 'action' },
) as PayloadActionCreator<number>
expectTypeOf(payloadActionCreator2).toMatchTypeOf<
ActionCreator<PayloadAction<number>>
>()
})
})
test('createAction() has type parameter for the action payload.', () => {
const increment = createAction<number, 'increment'>('increment')
expectTypeOf(increment).parameter(0).toBeNumber()
expectTypeOf(increment).parameter(0).not.toBeString()
})
test('createAction() type parameter is required, not inferred (defaults to `void`).', () => {
const increment = createAction('increment')
expectTypeOf(increment).parameter(0).not.toBeNumber()
expectTypeOf(increment().payload).not.toBeNumber()
})
test('createAction().type is a string literal.', () => {
const increment = createAction<number, 'increment'>('increment')
expectTypeOf(increment(1).type).toBeString()
expectTypeOf(increment(1).type).toEqualTypeOf<'increment'>()
expectTypeOf(increment(1).type).not.toMatchTypeOf<'other'>()
expectTypeOf(increment(1).type).not.toBeNumber()
})
test('type still present when using prepareAction', () => {
const strLenAction = createAction('strLen', (payload: string) => ({
payload: payload.length,
}))
expectTypeOf(strLenAction('test').type).toBeString()
})
test('changing payload type with prepareAction', () => {
const strLenAction = createAction('strLen', (payload: string) => ({
payload: payload.length,
}))
expectTypeOf(strLenAction('test').payload).toBeNumber()
expectTypeOf(strLenAction('test').payload).not.toBeString()
expectTypeOf(strLenAction('test')).not.toHaveProperty('error')
})
test('adding metadata with prepareAction', () => {
const strLenMetaAction = createAction('strLenMeta', (payload: string) => ({
payload,
meta: payload.length,
}))
expectTypeOf(strLenMetaAction('test').meta).toBeNumber()
expectTypeOf(strLenMetaAction('test').meta).not.toBeString()
expectTypeOf(strLenMetaAction('test')).not.toHaveProperty('error')
})
test('adding boolean error with prepareAction', () => {
const boolErrorAction = createAction('boolError', (payload: string) => ({
payload,
error: true,
}))
expectTypeOf(boolErrorAction('test').error).toBeBoolean()
expectTypeOf(boolErrorAction('test').error).not.toBeString()
})
test('adding string error with prepareAction', () => {
const strErrorAction = createAction('strError', (payload: string) => ({
payload,
error: 'this is an error',
}))
expectTypeOf(strErrorAction('test').error).toBeString()
expectTypeOf(strErrorAction('test').error).not.toBeBoolean()
})
test('regression test for https://github.com/reduxjs/redux-toolkit/issues/214', () => {
const action = createAction<{ input?: string }>('ACTION')
expectTypeOf(action({ input: '' }).payload.input).toEqualTypeOf<
string | undefined
>()
expectTypeOf(action({ input: '' }).payload.input).not.toBeNumber()
expectTypeOf(action).parameter(0).not.toMatchTypeOf({ input: 3 })
})
test('regression test for https://github.com/reduxjs/redux-toolkit/issues/224', () => {
const oops = createAction('oops', (x: any) => ({
payload: x,
error: x,
meta: x,
}))
expectTypeOf(oops('').payload).toBeAny()
expectTypeOf(oops('').error).toBeAny()
expectTypeOf(oops('').meta).toBeAny()
})
describe('createAction.match()', () => {
test('simple use case', () => {
const actionCreator = createAction<string, 'test'>('test')
const x: Action<string> = {} as any
if (actionCreator.match(x)) {
expectTypeOf(x.type).toEqualTypeOf<'test'>()
expectTypeOf(x.payload).toBeString()
} else {
expectTypeOf(x.type).not.toMatchTypeOf<'test'>()
expectTypeOf(x).not.toHaveProperty('payload')
}
})
test('special case: optional argument', () => {
const actionCreator = createAction<string | undefined, 'test'>('test')
const x: Action<string> = {} as any
if (actionCreator.match(x)) {
expectTypeOf(x.type).toEqualTypeOf<'test'>()
expectTypeOf(x.payload).toEqualTypeOf<string | undefined>()
}
})
test('special case: without argument', () => {
const actionCreator = createAction('test')
const x: Action<string> = {} as any
if (actionCreator.match(x)) {
expectTypeOf(x.type).toEqualTypeOf<'test'>()
expectTypeOf(x.payload).not.toMatchTypeOf<{}>()
}
})
test('special case: with prepareAction', () => {
const actionCreator = createAction('test', () => ({
payload: '',
meta: '',
error: false,
}))
const x: Action<string> = {} as any
if (actionCreator.match(x)) {
expectTypeOf(x.type).toEqualTypeOf<'test'>()
expectTypeOf(x.payload).toBeString()
expectTypeOf(x.meta).toBeString()
expectTypeOf(x.error).toBeBoolean()
expectTypeOf(x.payload).not.toBeNumber()
expectTypeOf(x.meta).not.toBeNumber()
expectTypeOf(x.error).not.toBeNumber()
}
})
test('potential use: as array filter', () => {
const actionCreator = createAction<string, 'test'>('test')
const x: Action<string>[] = []
expectTypeOf(x.filter(actionCreator.match)).toEqualTypeOf<
PayloadAction<string, 'test'>[]
>()
})
})
test('ActionCreatorWithOptionalPayload', () => {
expectTypeOf(createAction<string | undefined>('')).toEqualTypeOf<
ActionCreatorWithOptionalPayload<string | undefined>
>()
expectTypeOf(
createAction<void>(''),
).toEqualTypeOf<ActionCreatorWithoutPayload>()
assertType<ActionCreatorWithNonInferrablePayload>(createAction(''))
expectTypeOf(createAction<string>('')).toEqualTypeOf<
ActionCreatorWithPayload<string>
>()
expectTypeOf(
createAction('', (_: 0) => ({
payload: 1 as 1,
error: 2 as 2,
meta: 3 as 3,
})),
).toEqualTypeOf<ActionCreatorWithPreparedPayload<[0], 1, '', 2, 3>>()
const anyCreator = createAction<any>('')
expectTypeOf(anyCreator).toEqualTypeOf<ActionCreatorWithPayload<any>>()
expectTypeOf(anyCreator({}).payload).toBeAny()
})
test("Verify action creators should not be passed directly as arguments to React event handlers if there shouldn't be a payload", () => {
const emptyAction = createAction<void>('empty/action')
function TestComponent() {
// This typically leads to an error like:
// // A non-serializable value was detected in an action, in the path: `payload`.
// @ts-expect-error Should error because `void` and `MouseEvent` aren't compatible
return <button onClick={emptyAction}>+</button>
}
})
})