@shined/reactive
Version:
⚛️ Proxy-driven state library for JavaScript application, Intuitive, Flexible and Written in TypeScript.
132 lines (111 loc) • 4.55 kB
text/typescript
import { act, renderHook, waitFor } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { getSnapshot, proxy } from '../vanilla/index.js'
import { useSnapshot } from './use-snapshot.js'
describe('useSnapShot', () => {
it('should be defined', () => {
expect(useSnapshot).toBeDefined()
})
it('should return snapshot', () => {
const proxyState = proxy({ name: 'Bob' })
const { result } = renderHook(() => useSnapshot(proxyState))
expect(result.current).toEqual(getSnapshot(proxyState))
})
it('should update snapshot', async () => {
const proxyState = proxy({
address: {
city: {
name: 'Shanghai',
},
},
})
const { result } = renderHook(() => useSnapshot(proxyState))
act(() => {
// default async batch update is enabled for refine render performance
proxyState.address.city.name = 'any previous value'
proxyState.address.city.name = 'Nanjing'
})
// update are async, in this sync context, it will still be "Shanghai"
expect(result.current.address.city.name).toEqual('Shanghai')
await waitFor(() => {
// after async batch update, this will be "Nanjing"
expect(result.current.address.city.name).toEqual('Nanjing')
})
})
it('basic selector should be work', () => {
const proxyState = proxy({ name: 'Bob' })
const { result } = renderHook(() => useSnapshot(proxyState, (s) => s.name))
expect(result.current).toEqual('Bob')
})
it('return array selector should be work', () => {
const proxyState = proxy({ name: 'Bob', age: 32 })
const { result } = renderHook(() => {
const [name, age] = useSnapshot(proxyState, (s) => [s.name, s.age])
return [name, age]
})
expect(result.current).toMatchObject(['Bob', 32])
})
it('selector should refine render performance', async () => {
const proxyState = proxy({ name: 'Bob', other: 'other' })
const { result } = renderHook(() => useSnapshot(proxyState, (s) => s.name))
act(() => {
proxyState.other = 'other value'
})
})
it('should return updated proxyState snapshot with sync option', async () => {
const proxyState = proxy({ address: { city: { name: 'Shanghai' } } })
const { result } = renderHook(() => useSnapshot(proxyState, { sync: true }))
act(() => {
proxyState.address.city.name = 'Nanjing'
})
// when sync is enabled, it will be "Nanjing" as it is sync update
expect(result.current.address.city.name).toEqual('Nanjing')
})
it('should return updated proxyState snapshot with sync option', async () => {
const proxyState = proxy({ address: { city: { name: 'Shanghai' } } })
const { result } = renderHook(() => useSnapshot(proxyState, undefined, { sync: true }))
act(() => {
proxyState.address.city.name = 'Nanjing'
})
// when sync is enabled, it will be "Nanjing" as it is sync update
expect(result.current.address.city.name).toEqual('Nanjing')
})
it('should return updated proxyState snapshot with custom isEqual', async () => {
const proxyState = proxy({ address: { city: { name: 'Shanghai' } } })
const { result } = renderHook(() =>
useSnapshot(proxyState, (s) => s.address.city, { isEqual: (pre, cur) => pre === cur }),
)
act(() => {
proxyState.address.city.name = 'Nanjing'
})
// update are sync, in this sync context, it will still be "Shanghai"
expect(result.current.name).toEqual('Shanghai')
})
it('should return updated proxyState snapshot with custom isEqual', async () => {
const proxyState = proxy({ address: { city: { name: 'Shanghai' } } })
const { result } = renderHook(() =>
useSnapshot(proxyState, (s) => s.address.city, {
sync: true,
isEqual: (pre, cur) => pre === cur,
}),
)
act(() => {
proxyState.address.city.name = 'Nanjing'
})
expect(result.current.name).toEqual('Nanjing')
})
it('should return conditionally updated proxyState snapshot with custom isEqual', async () => {
const proxyState = proxy({ count: 0 })
const { result } = renderHook(() =>
useSnapshot(proxyState, (s) => s.count, { sync: true, isEqual: (pre, cur) => cur - pre < 2 }),
)
act(() => proxyState.count++)
expect(result.current).toEqual(0)
act(() => proxyState.count++)
expect(result.current).toEqual(2)
act(() => proxyState.count++)
expect(result.current).toEqual(2)
act(() => proxyState.count++)
expect(result.current).toEqual(4)
})
})