File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import SystemPage from './SystemPage'
import type { ResetTarget } from '../api/client'
const mocks = vi.hoisted(() => ({
getResetPreview: vi.fn(),
resetChannels: vi.fn(),
}))
vi.mock('../api/client', async (importOriginal) => ({
...(await importOriginal<typeof import('../api/client')>()),
getResetPreview: mocks.getResetPreview,
resetChannels: mocks.resetChannels,
}))
function target(overrides: Partial<ResetTarget> = {}): ResetTarget {
return {
orgId: 1,
orgNo: '001',
orgName: '국제방송교류재단',
stage: 1,
channels: [
{ kind: '문정원', channelId: 'ch-mj' },
{ kind: '법률검토', channelId: 'ch-law' },
],
...overrides,
}
}
async function typeConfirmAndRun(phrase = '채널 초기화') {
fireEvent.change(screen.getByLabelText(/실행하려면/), { target: { value: phrase } })
fireEvent.click(screen.getByText('채널 초기화 실행'))
fireEvent.click(await screen.findByText('초기화 실행'))
}
describe('SystemPage', () => {
beforeEach(() => {
vi.clearAllMocks()
mocks.getResetPreview.mockResolvedValue([target()])
mocks.resetChannels.mockResolvedValue({ archivedChannels: 2, clearedOrgs: 1, failures: [] })
})
it('초기화 대상을 기관·채널 수와 함께 미리 보여준다', async () => {
mocks.getResetPreview.mockResolvedValue([
target(),
target({ orgId: 2, orgNo: '002', orgName: '세종학당재단', channels: [{ kind: '문정원', channelId: 'c2' }] }),
])
render(<SystemPage />)
expect(await screen.findByText('대상 2개 기관 · 채널 3개')).toBeTruthy()
const rows = within(screen.getByTestId('reset-targets')).getAllByRole('row')
expect(rows).toHaveLength(3) // 헤더 + 2
expect(rows[1].textContent).toContain('문정원 · 법률검토')
})
it('확인 문구를 입력하기 전에는 실행 버튼이 잠겨 있다', async () => {
render(<SystemPage />)
await screen.findByTestId('reset-targets')
expect(screen.getByText('채널 초기화 실행')).toHaveProperty('disabled', true)
fireEvent.change(screen.getByLabelText(/실행하려면/), { target: { value: '초기화' } })
expect(screen.getByText('채널 초기화 실행')).toHaveProperty('disabled', true)
fireEvent.change(screen.getByLabelText(/실행하려면/), { target: { value: '채널 초기화' } })
expect(screen.getByText('채널 초기화 실행')).toHaveProperty('disabled', false)
})
it('실행 버튼을 눌러도 확인창에서 한 번 더 물어본다', async () => {
render(<SystemPage />)
await screen.findByTestId('reset-targets')
fireEvent.change(screen.getByLabelText(/실행하려면/), { target: { value: '채널 초기화' } })
fireEvent.click(screen.getByText('채널 초기화 실행'))
expect(await screen.findByText('정말 초기화할까요?')).toBeTruthy()
expect(mocks.resetChannels).not.toHaveBeenCalled()
fireEvent.click(screen.getByText('취소'))
expect(mocks.resetChannels).not.toHaveBeenCalled()
})
it('확인창에서 실행하면 문구와 함께 초기화를 요청하고 결과를 보여준다', async () => {
render(<SystemPage />)
await screen.findByTestId('reset-targets')
await typeConfirmAndRun()
await waitFor(() => expect(mocks.resetChannels).toHaveBeenCalledWith('채널 초기화'))
expect(await screen.findByText('채널 2개 보관, 기관 1곳 초기화')).toBeTruthy()
// 실행 후 목록을 다시 읽는다
expect(mocks.getResetPreview).toHaveBeenCalledTimes(2)
})
it('실패가 있으면 사유를 그대로 보여준다', async () => {
mocks.resetChannels.mockResolvedValue({
archivedChannels: 1,
clearedOrgs: 0,
failures: ['001 국제방송교류재단 (법률검토): 권한 없음'],
})
render(<SystemPage />)
await screen.findByTestId('reset-targets')
await typeConfirmAndRun()
expect(await screen.findByText(/실패 1건/)).toBeTruthy()
expect(screen.getByText(/권한 없음/)).toBeTruthy()
})
it('대상이 없으면 실행할 수 없다', async () => {
mocks.getResetPreview.mockResolvedValue([])
render(<SystemPage />)
expect(await screen.findByText('초기화할 채널이 없습니다.')).toBeTruthy()
fireEvent.change(screen.getByLabelText(/실행하려면/), { target: { value: '채널 초기화' } })
expect(screen.getByText('채널 초기화 실행')).toHaveProperty('disabled', true)
})
it('무엇이 남고 무엇이 사라지는지 화면에 적어 둔다', async () => {
render(<SystemPage />)
await screen.findByTestId('reset-targets')
expect(screen.getByText(/보관\(아카이브\)/)).toBeTruthy()
expect(screen.getByText(/그대로 남는다/)).toBeTruthy()
expect(screen.getByText(/사용자 계정도 건드리지 않는다/)).toBeTruthy()
})
})