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 { render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { CodeProvider } from './CodeProvider'
import { TEST_CODES, withCodes } from './fixtures'
import { useStages } from './stage'
import { badgeClass, barClass } from './tone'
import { useCodeLabel, useCodes, useScopedCodes, useSplitByFirstRow } from './useCodes'
const mocks = vi.hoisted(() => ({ getCodes: vi.fn() }))
vi.mock('../api/client', async (importOriginal) => ({
...(await importOriginal<typeof import('../api/client')>()),
getCodes: mocks.getCodes,
}))
beforeEach(() => {
mocks.getCodes.mockReset()
})
describe('useCodes', () => {
it('그룹의 선택지를 정렬순서대로 준다', () => {
function Probe() {
return <span>{useCodes('REVIEW_RESULT').map((c) => c.label).join('|')}</span>
}
render(withCodes(<Probe />))
expect(
screen.getByText('신유형 개방|계약서 등 재확인|권리처리 추진|개방불가|권리처리 추진 미희망'),
).toBeTruthy()
})
it('없는 그룹이면 빈 배열이라 화면이 죽지 않는다', () => {
function Probe() {
return <span data-testid="n">{useCodes('NO_SUCH_GROUP').length}</span>
}
render(withCodes(<Probe />))
expect(screen.getByTestId('n').textContent).toBe('0')
})
it('저장된 값의 표시명을 준다', () => {
function Probe() {
return <span>{useCodeLabel('CONTACT_CATEGORY', 'MJ')}</span>
}
render(withCodes(<Probe />))
// 엑셀에는 '주관기관'으로 오지만 화면에는 '문정원'으로 나와야 한다.
expect(screen.getByText('문정원')).toBeTruthy()
})
it('코드표에 없는 값이면 값 자체를 보여준다', () => {
function Probe() {
return <span>{useCodeLabel('CONTACT_METHOD', '문자')}</span>
}
render(withCodes(<Probe />))
// 과거 데이터가 빈칸으로 사라지는 것보다 원문이라도 보이는 편이 낫다.
expect(screen.getByText('문자')).toBeTruthy()
})
})
describe('공공누리 유형의 사용처 구분', () => {
function ScopeProbe({ scope }: { scope: string }) {
return <span>{useScopedCodes('KOGL_TYPE', scope).map((c) => c.code).join(',')}</span>
}
it('변호사 판정에는 보류가 있다', () => {
render(withCodes(<ScopeProbe scope="review" />))
expect(screen.getByText('0유형,1유형,2유형,3유형,4유형,개방불가,보류')).toBeTruthy()
})
it('권리처리 판정에는 보류가 없다', () => {
render(withCodes(<ScopeProbe scope="process" />))
expect(screen.getByText('0유형,1유형,2유형,3유형,4유형,개방불가')).toBeTruthy()
})
it('기존 부착 유형에는 조사표에서 온 값이 들어간다', () => {
render(withCodes(<ScopeProbe scope="prior" />))
expect(screen.getByText('0유형,1유형,2유형,3유형,4유형,유형 확인 필요,제4유형')).toBeTruthy()
})
it('라디오 첫 줄과 둘째 줄을 나눈다', () => {
function Probe() {
const { first, rest } = useSplitByFirstRow('KOGL_TYPE', 'review')
return (
<>
<span data-testid="first">{first.map((c) => c.code).join(',')}</span>
<span data-testid="rest">{rest.map((c) => c.code).join(',')}</span>
</>
)
}
render(withCodes(<Probe />))
expect(screen.getByTestId('first').textContent).toBe('0유형,개방불가,보류')
expect(screen.getByTestId('rest').textContent).toBe('1유형,2유형,3유형,4유형')
})
})
describe('useStages', () => {
function StageProbe() {
const stages = useStages()
return (
<>
<span data-testid="count">{stages.count}</span>
<span data-testid="label13">{stages.label(13)}</span>
<span data-testid="symbol13">{stages.symbol(13)}</span>
<span data-testid="symbol1">{stages.symbol(1)}</span>
<span data-testid="group5">{stages.groupKey(5)}</span>
<span data-testid="tone-assign">{stages.groupTone('assign')}</span>
<span data-testid="progress1">{stages.progressOf(1)}</span>
<span data-testid="progress7">{stages.progressOf(7)}</span>
<span data-testid="progress13">{stages.progressOf(13)}</span>
<span data-testid="completed-from">{stages.kpiThreshold('completed')}</span>
<span data-testid="counts12">{String(stages.countsToward('completed', 12))}</span>
<span data-testid="counts13">{String(stages.countsToward('completed', 13))}</span>
</>
)
}
it('단계 수와 라벨이 코드표에서 온다', () => {
render(withCodes(<StageProbe />))
expect(screen.getByTestId('count').textContent).toBe('13')
expect(screen.getByTestId('label13').textContent).toBe('보고서 제출 완료')
})
it('원문자는 번호에서 계산한다', () => {
render(withCodes(<StageProbe />))
expect(screen.getByTestId('symbol1').textContent).toBe('①')
expect(screen.getByTestId('symbol13').textContent).toBe('⑬')
})
it('진행상태는 1단계만 신청이고 13단계만 완료다', () => {
render(withCodes(<StageProbe />))
expect(screen.getByTestId('progress1').textContent).toBe('applied')
expect(screen.getByTestId('progress7').textContent).toBe('active')
expect(screen.getByTestId('progress13').textContent).toBe('done')
})
it('완료 KPI는 보고서가 올라온 13단계부터 센다', () => {
render(withCodes(<StageProbe />))
expect(screen.getByTestId('completed-from').textContent).toBe('13')
expect(screen.getByTestId('counts12').textContent).toBe('false')
expect(screen.getByTestId('counts13').textContent).toBe('true')
})
it('업무구간과 색이 코드표에서 온다', () => {
render(withCodes(<StageProbe />))
expect(screen.getByTestId('group5').textContent).toBe('check')
expect(screen.getByTestId('tone-assign').textContent).toBe('indigo')
})
})
describe('tone', () => {
it('의미 토큰을 실제 클래스로 바꾼다', () => {
expect(badgeClass('emerald')).toBe('bg-emerald-50 text-emerald-700')
expect(barClass('indigo')).toBe('bg-indigo-400')
})
it('모르는 토큰은 회색으로 떨어뜨린다', () => {
// 코드 관리 화면에서 오타가 들어가도 색만 밋밋해질 뿐 항목이 사라지면 안 된다.
expect(badgeClass('없는색')).toBe('bg-gray-100 text-gray-700')
expect(barClass(null)).toBe('bg-gray-300')
})
})
describe('CodeProvider', () => {
it('서버에서 선택지를 받아 아래 화면에 넘긴다', async () => {
mocks.getCodes.mockResolvedValue(TEST_CODES)
function Probe() {
return <span>{useCodes('PROCESS_STATUS').map((c) => c.label).join(',')}</span>
}
render(
<CodeProvider>
<Probe />
</CodeProvider>,
)
await waitFor(() => expect(screen.getByText('미처리,처리완료')).toBeTruthy())
})
it('선택지를 못 받으면 화면을 그리지 않고 오류를 보여준다', async () => {
mocks.getCodes.mockRejectedValue(new Error('서버 오류'))
function Probe() {
return <span>그려지면 안 됨</span>
}
render(
<CodeProvider>
<Probe />
</CodeProvider>,
)
// 빈 드롭다운으로 저장하면 값이 지워지므로 아예 안 그리는 편이 안전하다.
await waitFor(() => expect(screen.getByText(/선택지 정보를 불러오지 못했습니다/)).toBeTruthy())
expect(screen.queryByText('그려지면 안 됨')).toBeNull()
})
})