test(ssr): Validate state synchronization between server and client in React 18 using Zustand (#903) (#2088)

* test(ssr): Validate state synchronization between server and client in React 18 using Zustand (#903)

* test(ssr): dynamically import hydrateRoot for React 18 and skip if version < 18

* test(ssr): implement conditional describe based on React version

* test(ssr): Refactor SSR code using skipIf and importActual

* test(ssr): Refactor code using 'importActual' with a more specific type for 'hydrateRoot'

* test(ssr): remove async from the main test function

---------

Co-authored-by: Daishi Kato <dai-shi@users.noreply.github.com>
This commit is contained in:
JiWon Kim 2023-10-02 22:08:18 +09:00 committed by GitHub
parent 368478bfcb
commit 1e846b39b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

70
tests/ssr.test.tsx Normal file
View File

@ -0,0 +1,70 @@
import React, { useEffect } from 'react'
import { act, screen } from '@testing-library/react'
import { renderToString } from 'react-dom/server'
import { describe, expect, it, vi } from 'vitest'
import { create } from 'zustand'
interface BearStoreState {
bears: number
}
interface BearStoreAction {
increasePopulation: () => void
}
const initialState = { bears: 0 }
const useBearStore = create<BearStoreState & BearStoreAction>((set) => ({
...initialState,
increasePopulation: () => set(({ bears }) => ({ bears: bears + 1 })),
}))
function Counter() {
const { bears, increasePopulation } = useBearStore(
({ bears, increasePopulation }) => ({
bears,
increasePopulation,
})
)
useEffect(() => {
increasePopulation()
}, [increasePopulation])
return <div>bears: {bears}</div>
}
describe.skipIf(!React.version.startsWith('18'))(
'ssr behavior with react 18',
() => {
it('should handle different states between server and client correctly', async () => {
const { hydrateRoot } = await vi.importActual<
typeof import('react-dom/client')
>('react-dom/client')
const markup = renderToString(
<React.Suspense fallback={<div>Loading...</div>}>
<Counter />
</React.Suspense>
)
const container = document.createElement('div')
document.body.appendChild(container)
container.innerHTML = markup
expect(container.textContent).toContain('bears: 0')
await act(async () => {
hydrateRoot(
container,
<React.Suspense fallback={<div>Loading...</div>}>
<Counter />
</React.Suspense>
)
})
const bearCountText = await screen.findByText('bears: 1')
expect(bearCountText).not.toBeNull()
document.body.removeChild(container)
})
}
)