Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add unit tests #282

Merged
merged 11 commits into from
Jan 21, 2025
9 changes: 9 additions & 0 deletions src/tests/TestWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ThemeProvider } from '@mui/material/styles'

import type { ReactNode } from 'react'

import { theme } from '@/ui/style/theme'

export const TestWrapper = ({ children }: { children: ReactNode }) => {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>
}
13 changes: 13 additions & 0 deletions src/ui/components/CenteredSpinner.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { render, screen } from '@testing-library/react'
import { describe, expect, it } from 'vitest'

import { CenteredSpinner } from './CenteredSpinner'

describe('CenteredSpinner', () => {
it('should render the CircularProgress spinner', () => {
render(<CenteredSpinner />)

const spinner = screen.getByRole('progressbar')
expect(spinner).toBeInTheDocument()
})
})
25 changes: 25 additions & 0 deletions src/ui/components/ErrorComponent.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { render } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'

import { TestWrapper } from '@/tests/TestWrapper'

import { ErrorComponent } from './ErrorComponent'

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

describe('ErrorComponent', () => {
it('should render the error title and message', () => {
const message = 'Something went wrong'

const { getByText } = render(
<TestWrapper>
<ErrorComponent message={message} />
</TestWrapper>,
)

expect(getByText('errorOccured')).toBeInTheDocument()
expect(getByText(message)).toBeInTheDocument()
})
})
108 changes: 108 additions & 0 deletions src/ui/components/Modal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { fireEvent, render } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'

import { TestWrapper } from '@/tests/TestWrapper'

import { Modal } from './Modal'

describe('Modal', () => {
const defaultProps = {
isOpen: true,
dialogTitle: 'Modal Title',
dialogContent: 'This is the modal content',
buttons: [
{ label: 'Close', onClick: vi.fn(), autoFocus: false },
{ label: 'Confirm', onClick: vi.fn(), autoFocus: true },
],
onClose: vi.fn(),
}

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

it('should render the modal with provided props', () => {
const { getByText } = render(
<TestWrapper>
<Modal {...defaultProps} />
</TestWrapper>,
)

expect(getByText('Modal Title')).toBeInTheDocument()
expect(getByText('This is the modal content')).toBeInTheDocument()
expect(getByText('Close')).toBeInTheDocument()
expect(getByText('Confirm')).toBeInTheDocument()
})

it('should close the modal when close button is clicked', () => {
const { getByLabelText } = render(
<TestWrapper>
<Modal {...defaultProps} />
</TestWrapper>,
)
const closeButton = getByLabelText('close')

fireEvent.click(closeButton)

expect(defaultProps.onClose).toHaveBeenCalledTimes(1)
})

it('should not close the modal when clicked outside if mandatory prop is true', () => {
const props = { ...defaultProps, mandatory: true }
const { getByTestId } = render(
<TestWrapper>
<Modal {...props} />
</TestWrapper>,
)

const backdrop = getByTestId('modal-backdrop') // Backdrop div
fireEvent.click(backdrop)

expect(defaultProps.onClose).not.toHaveBeenCalled()
})

it('should trigger button onClick handler when buttons are clicked', () => {
const { getByText } = render(
<TestWrapper>
<Modal {...defaultProps} />
</TestWrapper>,
)

const confirmButton = getByText('Confirm')
fireEvent.click(confirmButton)

// Expect the onClick handler of the confirm button to be called
expect(defaultProps.buttons[1].onClick).toHaveBeenCalledTimes(1)

// as the mock buttons onClick does not do anything, the modal is still open so we can test other clicks
const closeButton = getByText('Close')
fireEvent.click(closeButton)

// Expect the onClick handler of the close button to be called
expect(defaultProps.buttons[0].onClick).toHaveBeenCalledTimes(1)
})

it('should not render the close button when mandatory is true', () => {
const props = { ...defaultProps, mandatory: true }
const { queryByLabelText } = render(
<TestWrapper>
<Modal {...props} />
</TestWrapper>,
)

expect(queryByLabelText('close')).not.toBeInTheDocument()
})

it('should render the modal dialog as closed when isOpen is false', () => {
const props = { ...defaultProps, isOpen: false }
const { queryByRole } = render(
<TestWrapper>
<Modal {...props} />
</TestWrapper>,
)

// Expect the dialog to not be in the document
const dialog = queryByRole('dialog')
expect(dialog).not.toBeInTheDocument()
})
})
2 changes: 1 addition & 1 deletion src/ui/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function Modal(props: ModalProps) {
}

return (
<Dialog open={isOpen} onClose={handleClose}>
<Dialog open={isOpen} onClose={handleClose} data-testid="modal-backdrop">
<Stack className={classes.dialog}>
<Stack className={classes.dialogHeader}>
<DialogTitle>{dialogTitle}</DialogTitle>
Expand Down
26 changes: 0 additions & 26 deletions src/ui/components/appVersion.tsx

This file was deleted.

104 changes: 104 additions & 0 deletions src/ui/components/orchestrator/Breadcrumb/Breadcrumb.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { fireEvent, render } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'

import type { GoToPage, OverviewItem } from '../lunaticType'
import { Breadcrumb } from './Breadcrumb'

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

describe('Breadcrumb Component', () => {
const goToPageMock: GoToPage = vi.fn()

const mockSequence: OverviewItem = {
id: '1',
type: 'sequence',
page: '1',
label: 'Sequence Label',
description: 'Sequence Description',
reached: true,
current: true,
children: [],
}

const mockSubSequence: OverviewItem = {
id: '2',
type: 'subSequence',
page: '2',
label: 'SubSequence Label',
description: 'SubSequence Description',
reached: true,
current: true,
children: [],
}

it('renders sequence and subSequence buttons when both are provided', () => {
const { getByText } = render(
<Breadcrumb
sequence={mockSequence}
subSequence={mockSubSequence}
goToPage={goToPageMock}
/>,
)

expect(getByText('Sequence Label')).toBeInTheDocument()
expect(getByText('SubSequence Label')).toBeInTheDocument()
})

it('calls goToSequencePage when sequence button is clicked', () => {
const { getByText } = render(
<Breadcrumb
sequence={mockSequence}
subSequence={mockSubSequence}
goToPage={goToPageMock}
/>,
)

const sequenceButton = getByText('Sequence Label')
fireEvent.click(sequenceButton)

expect(goToPageMock).toHaveBeenCalledWith({ page: '1' })
})

it('calls goToSubSequencePage when subSequence button is clicked', () => {
const { getByText } = render(
<Breadcrumb
sequence={mockSequence}
subSequence={mockSubSequence}
goToPage={goToPageMock}
/>,
)

const subSequenceButton = getByText('SubSequence Label')
fireEvent.click(subSequenceButton)

expect(goToPageMock).toHaveBeenCalledWith({ page: '2' })
})

it('renders only the sequence button when subSequence is undefined', () => {
const { getByText, queryByText } = render(
<Breadcrumb
sequence={mockSequence}
subSequence={undefined}
goToPage={goToPageMock}
/>,
)

expect(getByText('Sequence Label')).toBeInTheDocument()
expect(queryByText('SubSequence Label')).toBeNull()
})

it('renders only the subSequence button when sequence is undefined', () => {
const { getByText, queryByText } = render(
<Breadcrumb
sequence={undefined}
subSequence={mockSubSequence}
goToPage={goToPageMock}
/>,
)

expect(getByText('SubSequence Label')).toBeInTheDocument()
expect(queryByText('Sequence Label')).toBeNull()
})
})
5 changes: 2 additions & 3 deletions src/ui/components/orchestrator/Breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { useTranslation } from '@/i18n'

import type { GoToPage, OverviewItem } from '../lunaticType'

type BreadCrumbProps = {
type BreadcrumbProps = {
sequence: OverviewItem | undefined
subSequence: OverviewItem | undefined
iteration: number | undefined
goToPage: GoToPage
}

export function BreadCrumb(props: BreadCrumbProps) {
export function Breadcrumb(props: BreadcrumbProps) {
const { sequence, subSequence, goToPage } = props
const { classes, cx } = useStyles()
const { t } = useTranslation('navigationMessage')
Expand Down
Loading
Loading