import { configureStore } from '../configureStore' import { createSlice } from '../createSlice' import type { AutoBatchOptions } from '../autoBatchEnhancer' import { autoBatchEnhancer, prepareAutoBatched } from '../autoBatchEnhancer' import { delay } from '../utils' import { debounce } from 'lodash' interface CounterState { value: number } const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 } as CounterState, reducers: { incrementBatched: { // Batched, low-priority reducer(state) { state.value += 1 }, prepare: prepareAutoBatched(), }, // Not batched, normal priority decrementUnbatched(state) { state.value -= 1 }, }, }) const { incrementBatched, decrementUnbatched } = counterSlice.actions const makeStore = (autoBatchOptions?: AutoBatchOptions) => { return configureStore({ reducer: counterSlice.reducer, enhancers: (getDefaultEnhancers) => getDefaultEnhancers({ autoBatch: autoBatchOptions, }), }) } let store: ReturnType let subscriptionNotifications = 0 const cases: AutoBatchOptions[] = [ { type: 'tick' }, { type: 'raf' }, { type: 'timer', timeout: 0 }, { type: 'timer', timeout: 10 }, { type: 'timer', timeout: 20 }, { type: 'callback', queueNotification: debounce((notify: () => void) => { notify() }, 5), }, ] describe.each(cases)('autoBatchEnhancer: %j', (autoBatchOptions) => { beforeEach(() => { subscriptionNotifications = 0 store = makeStore(autoBatchOptions) store.subscribe(() => { subscriptionNotifications++ }) }) test('Does not alter normal subscription notification behavior', async () => { store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(1) store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(2) store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(3) store.dispatch(decrementUnbatched()) await delay(25) expect(subscriptionNotifications).toBe(4) }) test('Only notifies once if several batched actions are dispatched in a row', async () => { store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(incrementBatched()) await delay(25) expect(subscriptionNotifications).toBe(1) }) test('Notifies immediately if a non-batched action is dispatched', async () => { store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(1) store.dispatch(incrementBatched()) await delay(25) expect(subscriptionNotifications).toBe(2) }) test('Does not notify at end of tick if last action was normal priority', async () => { store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(incrementBatched()) expect(subscriptionNotifications).toBe(0) store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(1) store.dispatch(incrementBatched()) store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(2) store.dispatch(decrementUnbatched()) expect(subscriptionNotifications).toBe(3) await delay(25) expect(subscriptionNotifications).toBe(3) }) })