Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(test): stop testing deprecated features and test subscribe in vanilla #2244

Merged
merged 4 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions tests/shallow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { act, fireEvent, render } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { create } from 'zustand'
import { useShallow } from 'zustand/react/shallow'
import { createWithEqualityFn } from 'zustand/traditional'
charkour marked this conversation as resolved.
Show resolved Hide resolved
import { shallow } from 'zustand/vanilla/shallow'

describe('types', () => {
it('works with useBoundStore and array selector (#1107)', () => {
const useBoundStore = create(() => ({
const useBoundStore = createWithEqualityFn(() => ({
villages: [] as { name: string }[],
}))
const Component = () => {
Expand All @@ -18,7 +19,7 @@ describe('types', () => {
})

it('works with useBoundStore and string selector (#1107)', () => {
const useBoundStore = create(() => ({
const useBoundStore = createWithEqualityFn(() => ({
refetchTimestamp: '',
}))
const Component = () => {
Expand Down
126 changes: 8 additions & 118 deletions tests/subscribe.test.tsx
Original file line number Diff line number Diff line change
@@ -1,123 +1,13 @@
import { describe, expect, it, vi } from 'vitest'
import { describe, expect, it } from 'vitest'
import { create } from 'zustand'
import { subscribeWithSelector } from 'zustand/middleware'

describe('subscribe()', () => {
it('should not be called if new state identity is the same', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = create(() => initialState)

subscribe(spy)
setState(initialState)
expect(spy).not.toHaveBeenCalled()
})

it('should be called if new state identity is different', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, getState, subscribe } = create(() => initialState)

subscribe(spy)
setState({ ...getState() })
expect(spy).toHaveBeenCalledWith(initialState, initialState)
})

it('should not be called when state slice is the same', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = create(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s.value, spy)
setState({ other: 'b' })
expect(spy).not.toHaveBeenCalled()
})

it('should be called when state slice changes', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = create(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s.value, spy)
setState({ value: initialState.value + 1 })
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(initialState.value + 1, initialState.value)
})

it('should not be called when equality checker returns true', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = create(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s, spy, { equalityFn: () => true })
setState({ value: initialState.value + 2 })
expect(spy).not.toHaveBeenCalled()
})

it('should be called when equality checker returns false', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = create(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s.value, spy, { equalityFn: () => false })
setState({ value: initialState.value + 2 })
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(initialState.value + 2, initialState.value)
})

it('should unsubscribe correctly', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = create(
subscribeWithSelector(() => initialState),
)

const unsub = subscribe((s) => s.value, spy)

setState({ value: initialState.value + 1 })
unsub()
setState({ value: initialState.value + 2 })

expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(initialState.value + 1, initialState.value)
})

it('should keep consistent behavior with equality check', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { getState, setState, subscribe } = create(
subscribeWithSelector(() => initialState),
)

const isRoughEqual = (x: number, y: number) => Math.abs(x - y) < 1
setState({ value: 0 })
spy.mockReset()
const spy2 = vi.fn()
let prevValue = getState().value
const unsub = subscribe((s) => {
if (isRoughEqual(prevValue, s.value)) {
// skip assuming values are equal
return
}
spy(s.value, prevValue)
prevValue = s.value
})
const unsub2 = subscribe((s) => s.value, spy2, { equalityFn: isRoughEqual })
setState({ value: 0.5 })
setState({ value: 1 })
unsub()
unsub2()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(1, 0)
expect(spy2).toHaveBeenCalledTimes(1)
expect(spy2).toHaveBeenCalledWith(1, 0)
it('should correctly have access to subscribe', () => {
const { subscribe } = create(() => ({ value: 1 }))
expect({ subscribe }).toMatchInlineSnapshot(`
{
"subscribe": [Function],
}
`)
})
charkour marked this conversation as resolved.
Show resolved Hide resolved
})
123 changes: 123 additions & 0 deletions tests/vanilla/subscribe.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { describe, expect, it, vi } from 'vitest'
import { subscribeWithSelector } from 'zustand/middleware'
import { createStore } from 'zustand/vanilla'

describe('subscribe()', () => {
charkour marked this conversation as resolved.
Show resolved Hide resolved
it('should not be called if new state identity is the same', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = createStore(() => initialState)

subscribe(spy)
setState(initialState)
expect(spy).not.toHaveBeenCalled()
})

it('should be called if new state identity is different', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, getState, subscribe } = createStore(() => initialState)

subscribe(spy)
setState({ ...getState() })
expect(spy).toHaveBeenCalledWith(initialState, initialState)
})

it('should not be called when state slice is the same', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = createStore(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s.value, spy)
setState({ other: 'b' })
expect(spy).not.toHaveBeenCalled()
})

it('should be called when state slice changes', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = createStore(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s.value, spy)
setState({ value: initialState.value + 1 })
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(initialState.value + 1, initialState.value)
})

it('should not be called when equality checker returns true', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = createStore(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s, spy, { equalityFn: () => true })
setState({ value: initialState.value + 2 })
expect(spy).not.toHaveBeenCalled()
})

it('should be called when equality checker returns false', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = createStore(
subscribeWithSelector(() => initialState),
)

subscribe((s) => s.value, spy, { equalityFn: () => false })
setState({ value: initialState.value + 2 })
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(initialState.value + 2, initialState.value)
})

it('should unsubscribe correctly', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { setState, subscribe } = createStore(
subscribeWithSelector(() => initialState),
)

const unsub = subscribe((s) => s.value, spy)

setState({ value: initialState.value + 1 })
unsub()
setState({ value: initialState.value + 2 })

expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(initialState.value + 1, initialState.value)
})

it('should keep consistent behavior with equality check', () => {
const spy = vi.fn()
const initialState = { value: 1, other: 'a' }
const { getState, setState, subscribe } = createStore(
subscribeWithSelector(() => initialState),
)

const isRoughEqual = (x: number, y: number) => Math.abs(x - y) < 1
setState({ value: 0 })
spy.mockReset()
const spy2 = vi.fn()
let prevValue = getState().value
const unsub = subscribe((s) => {
if (isRoughEqual(prevValue, s.value)) {
// skip assuming values are equal
return
}
spy(s.value, prevValue)
prevValue = s.value
})
const unsub2 = subscribe((s) => s.value, spy2, { equalityFn: isRoughEqual })
setState({ value: 0.5 })
setState({ value: 1 })
unsub()
unsub2()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(1, 0)
expect(spy2).toHaveBeenCalledTimes(1)
expect(spy2).toHaveBeenCalledWith(1, 0)
})
})
Loading