Build NapCat Artifacts / Windows Loader Test (push) Canceled after 0s
Build NapCat Artifacts / Type Check & Test (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Framework (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Shell (push) Canceled after 0s
209 lines
6.1 KiB
Plaintext
209 lines
6.1 KiB
Plaintext
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<void>(),
|
|
},
|
|
// 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<typeof makeStore>
|
|
|
|
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)
|
|
})
|
|
})
|
|
|
|
describe.each(cases)(
|
|
'autoBatchEnhancer with fake timers: %j',
|
|
(autoBatchOptions) => {
|
|
beforeAll(() => {
|
|
vitest.useFakeTimers({
|
|
toFake: ['setTimeout', 'queueMicrotask', 'requestAnimationFrame'],
|
|
})
|
|
})
|
|
afterAll(() => {
|
|
vitest.useRealTimers()
|
|
})
|
|
beforeEach(() => {
|
|
subscriptionNotifications = 0
|
|
store = makeStore(autoBatchOptions)
|
|
|
|
store.subscribe(() => {
|
|
subscriptionNotifications++
|
|
})
|
|
})
|
|
test('Does not alter normal subscription notification behavior', () => {
|
|
store.dispatch(decrementUnbatched())
|
|
expect(subscriptionNotifications).toBe(1)
|
|
store.dispatch(decrementUnbatched())
|
|
expect(subscriptionNotifications).toBe(2)
|
|
store.dispatch(decrementUnbatched())
|
|
expect(subscriptionNotifications).toBe(3)
|
|
store.dispatch(decrementUnbatched())
|
|
|
|
vitest.runAllTimers()
|
|
|
|
expect(subscriptionNotifications).toBe(4)
|
|
})
|
|
|
|
test('Only notifies once if several batched actions are dispatched in a row', () => {
|
|
store.dispatch(incrementBatched())
|
|
expect(subscriptionNotifications).toBe(0)
|
|
store.dispatch(incrementBatched())
|
|
expect(subscriptionNotifications).toBe(0)
|
|
store.dispatch(incrementBatched())
|
|
expect(subscriptionNotifications).toBe(0)
|
|
store.dispatch(incrementBatched())
|
|
|
|
vitest.runAllTimers()
|
|
|
|
expect(subscriptionNotifications).toBe(1)
|
|
})
|
|
|
|
test('Notifies immediately if a non-batched action is dispatched', () => {
|
|
store.dispatch(incrementBatched())
|
|
expect(subscriptionNotifications).toBe(0)
|
|
store.dispatch(incrementBatched())
|
|
expect(subscriptionNotifications).toBe(0)
|
|
store.dispatch(decrementUnbatched())
|
|
expect(subscriptionNotifications).toBe(1)
|
|
store.dispatch(incrementBatched())
|
|
|
|
vitest.runAllTimers()
|
|
|
|
expect(subscriptionNotifications).toBe(2)
|
|
})
|
|
|
|
test('Does not notify at end of tick if last action was normal priority', () => {
|
|
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)
|
|
|
|
vitest.runAllTimers()
|
|
|
|
expect(subscriptionNotifications).toBe(3)
|
|
})
|
|
},
|
|
)
|