JotaiJotai

Jotai
React 原始而灵活的状态管理

测试

我们回应了测试库的指导原则

  • "你的测试越像你的软件被使用的方式,它们就能给你更多的信心。"

我们鼓励你像用户会与你的原子和组件交互那样编写测试,因此将Jotai视为一个实现细节。

这里有一个使用React测试库的例子:

Counter.tsx

import { atom, useAtom } from 'jotai'
export const countAtom = atom(0)
export function Counter() {
const [count, setCount] = useAtom(countAtom)
return (
<h1>
<p>{count}</p>
<button onClick={() => setCount((c) => c + 1)}>one up</button>
</h1>
)
}

Counter.test.ts

import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import { Counter } from './Counter'
test('should increment counter', () => {
// Arrange
render(<Counter />)
const counter = screen.getByText('0')
const incrementButton = screen.getByText('one up')
// Act
fireEvent.click(incrementButton)
// Assert
expect(counter.textContent).toEqual('1')
})

注入值

你可能想在开始一些测试之前向你的原子注入任意值。也许计数器应该限制到100。让我们看看如何测试它在达到100后不会增加。为了做到这一点,只需使用一个Provider,并导出你的原子以便填充。

import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import { useHydrateAtoms } from 'jotai/utils'
import { countAtom, Counter } from './Counter'
import { Provider } from 'jotai'
const HydrateAtoms = ({ initialValues, children }) => {
useHydrateAtoms(initialValues)
return children
}
const TestProvider = ({ initialValues, children }) => (
<Provider>
<HydrateAtoms initialValues={initialValues}>{children}</HydrateAtoms>
</Provider>
)
const CounterProvider = () => {
return (
<TestProvider initialValues={[[countAtom, 100]]}>
<Counter />
</TestProvider>
)
}
test('should not increment on max (100)', () => {
render(<CounterProvider />)
const counter = screen.getByText('100')
const incrementButton = screen.getByText('one up')
fireEvent.click(incrementButton)
expect(counter.textContent).toEqual('100')
})

自定义钩子

如果你有复杂的原子,有时你可能想要单独测试它们。

为此,你可以使用React Hooks测试库。下面是一个例子:

countAtom.ts

import { useAtom } from 'jotai'
import { atomWithReducer } from 'jotai/utils'
const reducer = (state: number, action?: 'INCREASE' | 'DECREASE') => {
switch (action) {
case 'INCREASE':
return state + 1
case 'DECREASE':
return state - 1
case undefined:
return state
}
}
export const countAtom = atomWithReducer(0, reducer)

countAtom.test.ts

import { renderHook, act } from '@testing-library/react-hooks'
import { useAtom } from 'jotai'
import { countAtom } from './countAtom'
test('should increment counter', () => {
const { result } = renderHook(() => useAtom(countAtom))
act(() => {
result.current[1]('INCREASE')
})
expect(result.current[0]).toBe(1)
})

使用React-Native的例子

当然,你也可以用相同的方式测试React-Native组件,无论是否使用Provider

import React from 'react'
import { render, fireEvent } from '@testing-library/react-native'
import { Counter } from './counter'
test('should increment counter', () => {
// 安排
const { getByText } = render(<Counter />)
const counter = getByText('0')
const incrementButton = getByText('one up')
// 执行
fireEvent.press(incrementButton)
// 断言
expect(counter.props.children.toString()).toEqual('1')
})