f1181e8510
Reviewed-on: #413 Co-authored-by: miteruzo <miteruzo@naver.com> Co-committed-by: miteruzo <miteruzo@naver.com>
78 行
2.7 KiB
TypeScript
78 行
2.7 KiB
TypeScript
import { fireEvent, screen, waitFor, within } from '@testing-library/react'
|
|
import { useState } from 'react'
|
|
import { useLocation, useNavigate } from 'react-router-dom'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
|
|
import { useUnsavedChangesGuard } from '@/lib/useUnsavedChangesGuard'
|
|
import { renderWithProviders } from '@/test/render'
|
|
|
|
const GuardHarness = () => {
|
|
const [dirty, setDirty] = useState (true)
|
|
const location = useLocation ()
|
|
const navigate = useNavigate ()
|
|
const discard = vi.fn (() => setDirty (false))
|
|
const { allowNextNavigation } = useUnsavedChangesGuard ({
|
|
dirty,
|
|
onDiscard: discard })
|
|
|
|
return (
|
|
<>
|
|
<output aria-label="location">{location.pathname}{location.search}</output>
|
|
<button type="button" onClick={() => navigate ('/next?tab=one')}>move</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
allowNextNavigation ()
|
|
navigate ('/allowed')
|
|
}}>
|
|
allowed move
|
|
</button>
|
|
</>)
|
|
}
|
|
|
|
describe ('useUnsavedChangesGuard', () => {
|
|
it ('blocks route changes and resets a cancelled transition', async () => {
|
|
renderWithProviders (<GuardHarness/>, { route: '/current' })
|
|
|
|
fireEvent.click (screen.getByRole ('button', { name: 'move' }))
|
|
|
|
expect (within (await screen.findByRole ('dialog')).getByText (
|
|
'変更が破棄してページ移動しますか?')).toBeInTheDocument ()
|
|
expect (screen.getByLabelText ('location')).toHaveTextContent ('/current')
|
|
|
|
fireEvent.click (screen.getByRole ('button', { name: '取消' }))
|
|
|
|
await waitFor (() => {
|
|
expect (screen.queryByRole ('dialog')).not.toBeInTheDocument ()
|
|
})
|
|
expect (screen.getByLabelText ('location')).toHaveTextContent ('/current')
|
|
})
|
|
|
|
it ('proceeds with the blocked transition after discard is confirmed', async () => {
|
|
renderWithProviders (<GuardHarness/>, { route: '/current' })
|
|
|
|
fireEvent.click (screen.getByRole ('button', { name: 'move' }))
|
|
fireEvent.click (await screen.findByRole ('button', {
|
|
name: '変更を破棄して移動' }))
|
|
|
|
await waitFor (() => {
|
|
expect (screen.getByLabelText ('location')).toHaveTextContent ('/next?tab=one')
|
|
})
|
|
})
|
|
|
|
it ('allows only the next navigation without leaving a bypass token', async () => {
|
|
renderWithProviders (<GuardHarness/>, { route: '/current' })
|
|
|
|
fireEvent.click (screen.getByRole ('button', { name: 'allowed move' }))
|
|
await waitFor (() => {
|
|
expect (screen.getByLabelText ('location')).toHaveTextContent ('/allowed')
|
|
})
|
|
|
|
fireEvent.click (screen.getByRole ('button', { name: 'move' }))
|
|
|
|
expect (within (await screen.findByRole ('dialog')).getByText (
|
|
'変更が破棄してページ移動しますか?')).toBeInTheDocument ()
|
|
expect (screen.getByLabelText ('location')).toHaveTextContent ('/allowed')
|
|
})
|
|
})
|