Skip to content

Commit

Permalink
test: add unit tests on pages
Browse files Browse the repository at this point in the history
  • Loading branch information
QRuhier committed Jan 17, 2025
1 parent f97fedd commit 1bbcd8b
Show file tree
Hide file tree
Showing 9 changed files with 688 additions and 1 deletion.
51 changes: 51 additions & 0 deletions src/ui/pages/Error/Error.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { render } from '@testing-library/react'
import { isRouteErrorResponse, useRouteError } from 'react-router-dom'
import { afterEach, describe, expect, it, vi } from 'vitest'

import { ErrorComponent } from '@/ui/components/ErrorComponent'

import { ErrorPage } from './Error'

vi.mock('react-router-dom', () => ({
useRouteError: vi.fn(),
isRouteErrorResponse: vi.fn(),
}))
vi.mock('@/i18n', () => ({
useTranslation: () => ({ t: (keyMessage: string) => keyMessage }),
}))
vi.mock('@/ui/components/ErrorComponent', () => ({
ErrorComponent: vi.fn(),
}))

afterEach(() => {
vi.clearAllMocks()
})

describe('ErrorPage', () => {
it('calls ErrorComponent with the correct message for instance of Error', () => {
const mockError = new Error('Something went wrong')
vi.mocked(useRouteError).mockReturnValue(mockError)

render(<ErrorPage />)

expect(ErrorComponent).toHaveBeenCalledWith(
expect.objectContaining({ message: 'Something went wrong' }),
{},
)
})

it('renders ErrorComponent with the correct message for RouteErrorResponse', () => {
const mockRouteError = { status: 404, statusText: 'Not Found' }
vi.mocked(useRouteError).mockReturnValue(mockRouteError)
vi.mocked(isRouteErrorResponse).mockReturnValue(true)

render(<ErrorPage />)

expect(ErrorComponent).toHaveBeenCalledWith(
expect.objectContaining({
message: 'error 404 : Not Found',
}),
{},
)
})
})
52 changes: 52 additions & 0 deletions src/ui/pages/External/External.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { render } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'

import { CenteredSpinner } from '@/ui/components/CenteredSpinner'
import { ErrorComponent } from '@/ui/components/ErrorComponent'

import { ExternalRessources } from './External'
import useScript from './useScript'

vi.mock('@/i18n', () => ({
getTranslation: () => ({ t: (keyMessage: string) => keyMessage }),
}))
vi.mock('@/ui/components/ErrorComponent', () => ({
ErrorComponent: vi.fn(),
}))
vi.mock('@/ui/components/CenteredSpinner', () => ({
CenteredSpinner: vi.fn(),
}))
vi.mock('./useScript', () => ({
default: vi.fn(),
}))

describe('ExternalRessources', () => {
it('renders CenteredSpinner when status is "loading"', () => {
vi.mocked(useScript).mockReturnValue('loading')

render(<ExternalRessources />)

expect(CenteredSpinner).toHaveBeenCalled()
})

it('renders <capmi-app /> when status is "ready"', () => {
vi.mocked(useScript).mockReturnValue('ready')

const { container } = render(<ExternalRessources />)

// Check that <capmi-app /> is rendered in the container
const capmiAppElement = container.querySelector('capmi-app')
expect(capmiAppElement).toBeInTheDocument()
})

it('renders ErrorComponent with correct message when status is "error"', () => {
vi.mocked(useScript).mockReturnValue('error')

render(<ExternalRessources />)

expect(ErrorComponent).toHaveBeenCalledWith(
expect.objectContaining({ message: 'externalResourcesLoadedError' }),
{},
)
})
})
62 changes: 62 additions & 0 deletions src/ui/pages/collect/Collect.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { render } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'

import { useCore } from '@/core'
import { Orchestrator } from '@/ui/components/orchestrator/Orchestrator'
import { useLoaderData } from '@/ui/routing/utils'

import { Collect } from './Collect'

vi.mock('@/core', () => ({
useCore: vi.fn(),
}))
vi.mock('@/ui/routing/utils', () => ({
useLoaderData: vi.fn(),
}))
vi.mock('@/ui/components/orchestrator/Orchestrator', () => ({
Orchestrator: vi.fn(),
}))

describe('Collect Component', () => {
it('renders Orchestrator with the correct props', () => {
const mockLoaderData = {
questionnaire: { id: 'q1', title: 'Questionnaire 1' },
surveyUnit: { id: 'su1', name: 'Survey Unit 1' },
}

vi.mocked(useLoaderData).mockReturnValue(mockLoaderData)

const mockCollectSurvey = {
getReferentiel: vi.fn(),
changePage: vi.fn(),
changeSurveyUnitState: vi.fn(),
quit: vi.fn(),
retrieveQuestionnaireId: vi.fn(),
loader: vi.fn(),
}

const mockCore = {
functions: {
collectSurvey: mockCollectSurvey,
},
}

vi.mocked(useCore).mockReturnValue(mockCore as any)

render(<Collect />)

expect(Orchestrator).toHaveBeenCalledWith(
expect.objectContaining({
source: mockLoaderData.questionnaire,
surveyUnit: mockLoaderData.surveyUnit,
readonly: false,
onQuit: mockCollectSurvey.quit,
onDefinitiveQuit: mockCollectSurvey.quit,
onChangePage: mockCollectSurvey.changePage,
getReferentiel: mockCollectSurvey.getReferentiel,
onChangeSurveyUnitState: mockCollectSurvey.changeSurveyUnitState,
}),
{},
)
})
})
131 changes: 131 additions & 0 deletions src/ui/pages/review/Review.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { render } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'

import { useCore } from '@/core'
import type { SurveyUnit } from '@/core/model'
import { Modal } from '@/ui/components/Modal'
import { Orchestrator } from '@/ui/components/orchestrator/Orchestrator'
import { useLoaderData } from '@/ui/routing/utils'

import { Review } from './Review'

vi.mock('@/ui/routing/utils', () => ({
useLoaderData: vi.fn(),
}))

vi.mock('@/core', () => ({
useCore: vi.fn(),
}))

vi.mock('@/i18n', () => ({
useTranslation: () => ({ t: (keyMessage: string) => keyMessage }),
}))

vi.mock('@/ui/components/Modal', () => ({
Modal: vi.fn(),
}))

vi.mock('@/ui/components/orchestrator/Orchestrator', () => ({
Orchestrator: vi.fn(),
}))

describe('Review', () => {
afterEach(() => {
vi.clearAllMocks()
})

it('renders Orchestrator with correct props', () => {
const mockLoaderData = {
questionnaire: { id: 'q1' },
surveyUnit: { id: 'su1' },
}

vi.mocked(useLoaderData).mockReturnValue(mockLoaderData)

const mockReviewSurvey = {
getReferentiel: vi.fn(),
}

const mockCore = {
functions: {
reviewSurvey: mockReviewSurvey,
},
}

vi.mocked(useCore).mockReturnValue(mockCore as any)

render(<Review />)

expect(Orchestrator).toHaveBeenCalledWith(
expect.objectContaining({
source: mockLoaderData.questionnaire,
surveyUnit: mockLoaderData.surveyUnit,
readonly: true,
onQuit: expect.any(Function),
onDefinitiveQuit: expect.any(Function),
onChangePage: undefined,
getReferentiel: mockReviewSurvey.getReferentiel,
}),
{},
)
})

it('opens and closes the quit modal', () => {
const mockLoaderData = {
questionnaire: { id: 'q1' },
surveyUnit: { id: 'su1' },
}

vi.mocked(useLoaderData).mockReturnValue(mockLoaderData)

const mockReviewSurvey = {
getReferentiel: vi.fn(),
}

const mockCore = {
functions: {
reviewSurvey: mockReviewSurvey,
},
}

vi.mocked(useCore).mockReturnValue(mockCore as any)

const { rerender } = render(<Review />)

// Simulate Orchestrator's onQuit call
const { onQuit } = vi.mocked(Orchestrator).mock.calls[0][0]

if (onQuit) {
onQuit(mockLoaderData.surveyUnit as SurveyUnit)
}

rerender(<Review />)

expect(Modal).toHaveBeenCalledWith(
expect.objectContaining({
isOpen: true,
dialogTitle: 'reviewQuitTitle',
dialogContent: 'reviewQuitContent',
buttons: expect.arrayContaining([
expect.objectContaining({ label: 'cancel', autoFocus: false }),
]),
onClose: expect.any(Function),
}),
expect.anything(),
)

// Simulate Modal's onClose call
const modalProps = vi.mocked(Modal).mock.calls[0][0]
modalProps.onClose()

// Rerender to reflect state change
rerender(<Review />)

expect(Modal).toHaveBeenLastCalledWith(
expect.objectContaining({
isOpen: false,
}),
expect.anything(),
)
})
})
99 changes: 99 additions & 0 deletions src/ui/pages/synchronize/LoadingDisplay.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import LinearProgress from '@mui/material/LinearProgress'
import { render } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'

import { LoadingDisplay } from './LoadingDisplay'

vi.mock('@/i18n', () => ({
useTranslation: () => ({ t: (keyMessage: string) => keyMessage }),
}))

vi.mock('@mui/material/LinearProgress', () => ({
__esModule: true,
default: vi.fn(),
}))

afterEach(() => {
vi.clearAllMocks()
})

describe('LoadingDisplay Component', () => {
it('renders synchronization title and step title', () => {
const props = {
syncStepTitle: 'sync step',
progressBars: [{ label: 'Progress 1', progress: 50 }],
}

const { getByText } = render(<LoadingDisplay {...props} />)

expect(getByText('synchronizationInProgress')).toBeInTheDocument()
expect(getByText('sync step')).toBeInTheDocument()
})

it('renders progress bars with labels', () => {
const props = {
syncStepTitle: 'sync step',
progressBars: [
{ label: 'Progress 1', progress: 50 },
{ label: 'Progress 2', progress: 75, extraTitle: 'Extra Info' },
],
}

const { getByText } = render(<LoadingDisplay {...props} />)

// Check progress labels
expect(getByText('Progress 1')).toBeInTheDocument()
expect(getByText('Progress 2: Extra Info')).toBeInTheDocument()

// Check progress bars
expect(LinearProgress).toHaveBeenCalledTimes(2)
expect(LinearProgress).toHaveBeenCalledWith(
expect.objectContaining({
variant: 'determinate',
value: 50,
}),
{},
)
expect(LinearProgress).toHaveBeenCalledWith(
expect.objectContaining({
variant: 'determinate',
value: 75,
}),
{},
)
})

it('renders progress bars without labels', () => {
const props = {
syncStepTitle: 'sync step',
progressBars: [{ progress: 50 }, { progress: 75 }],
}

render(<LoadingDisplay {...props} />)

// Check progress bars
expect(LinearProgress).toHaveBeenCalledTimes(2)
expect(LinearProgress).toHaveBeenCalledWith(
expect.objectContaining({
variant: 'determinate',
value: 50,
}),
{},
)
expect(LinearProgress).toHaveBeenCalledWith(
expect.objectContaining({
variant: 'determinate',
value: 75,
}),
{},
)
})

it('handles empty progressBars', () => {
const props = { syncStepTitle: 'sync step', progressBars: [] }
render(<LoadingDisplay {...props} />)

// Check that no progress bars are rendered
expect(LinearProgress).not.toHaveBeenCalled()
})
})
Loading

0 comments on commit 1bbcd8b

Please sign in to comment.