Skip to content

Commit

Permalink
test: finished all ui components test (janhq#3588)
Browse files Browse the repository at this point in the history
* test: finished all ui components test

* chore: update naming of mock handle change modal test
  • Loading branch information
urmauur authored Sep 9, 2024
1 parent fe9936c commit ac67247
Show file tree
Hide file tree
Showing 15 changed files with 800 additions and 9 deletions.
1 change: 1 addition & 0 deletions joi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"jest-environment-jsdom": "^29.7.0",
"jest-transform-css": "^6.0.1",
Expand Down
36 changes: 29 additions & 7 deletions joi/src/core/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ import { Button, buttonConfig } from './index'
// Mock the styles
jest.mock('./styles.scss', () => ({}))

describe('Button', () => {
describe('@joi/core/Button', () => {
it('renders with default props', () => {
render(<Button>Click me</Button>)
const button = screen.getByRole('button', { name: /click me/i })
expect(button).toBeInTheDocument()
expect(button).toHaveClass('btn btn--primary btn--medium btn--solid')
})

it('applies custom className', () => {
render(<Button className="custom-class">Test Button</Button>)
const badge = screen.getByText('Test Button')
expect(badge).toHaveClass('custom-class')
})

it('renders as a child component when asChild is true', () => {
render(
<Button asChild>
Expand Down Expand Up @@ -58,11 +64,27 @@ describe('Button', () => {
expect(button).toHaveClass('btn btn--block')
})

it('merges custom className with generated classes', () => {
render(<Button className="custom-class">Custom Class Button</Button>)
const button = screen.getByRole('button', { name: /custom class button/i })
expect(button).toHaveClass(
'btn btn--primary btn--medium btn--solid custom-class'
)
it('fails when a new theme is added without updating the test', () => {
const expectedThemes = ['primary', 'ghost', 'icon', 'destructive']
const actualThemes = Object.keys(buttonConfig.variants.theme)
expect(actualThemes).toEqual(expectedThemes)
})

it('fails when a new variant is added without updating the test', () => {
const expectedVariant = ['solid', 'soft', 'outline']
const actualVariants = Object.keys(buttonConfig.variants.variant)
expect(actualVariants).toEqual(expectedVariant)
})

it('fails when a new size is added without updating the test', () => {
const expectedSizes = ['small', 'medium', 'large']
const actualSizes = Object.keys(buttonConfig.variants.size)
expect(actualSizes).toEqual(expectedSizes)
})

it('fails when a new variant CVA is added without updating the test', () => {
const expectedVariantsCVA = ['theme', 'variant', 'size', 'block']
const actualVariant = Object.keys(buttonConfig.variants)
expect(actualVariant).toEqual(expectedVariantsCVA)
})
})
50 changes: 50 additions & 0 deletions joi/src/core/Checkbox/Checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Checkbox } from './index'

// Mock the styles
jest.mock('./styles.scss', () => ({}))

describe('@joi/core/Checkbox', () => {
it('renders correctly with label', () => {
render(<Checkbox id="test-checkbox" label="Test Checkbox" />)
expect(screen.getByLabelText('Test Checkbox')).toBeInTheDocument()
})

it('renders with helper description', () => {
render(<Checkbox id="test-checkbox" helperDescription="Helper text" />)
expect(screen.getByText('Helper text')).toBeInTheDocument()
})

it('renders error message when provided', () => {
render(<Checkbox id="test-checkbox" errorMessage="Error occurred" />)
expect(screen.getByText('Error occurred')).toBeInTheDocument()
})

it('calls onChange when clicked', () => {
const mockOnChange = jest.fn()
render(
<Checkbox
id="test-checkbox"
label="Test Checkbox"
onChange={mockOnChange}
/>
)

fireEvent.click(screen.getByLabelText('Test Checkbox'))
expect(mockOnChange).toHaveBeenCalledTimes(1)
})

it('applies custom className', () => {
render(<Checkbox id="test-checkbox" className="custom-class" />)
expect(screen.getByRole('checkbox').parentElement).toHaveClass(
'custom-class'
)
})

it('disables the checkbox when disabled prop is true', () => {
render(<Checkbox id="test-checkbox" label="Disabled Checkbox" disabled />)
expect(screen.getByLabelText('Disabled Checkbox')).toBeDisabled()
})
})
53 changes: 53 additions & 0 deletions joi/src/core/Input/Input.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Input } from './index'

// Mock the styles import
jest.mock('./styles.scss', () => ({}))

describe('@joi/core/Input', () => {
it('renders correctly', () => {
render(<Input placeholder="Test input" />)
expect(screen.getByPlaceholderText('Test input')).toBeInTheDocument()
})

it('applies custom className', () => {
render(<Input className="custom-class" />)
expect(screen.getByRole('textbox')).toHaveClass('custom-class')
})

it('aligns text to the right when textAlign prop is set', () => {
render(<Input textAlign="right" />)
expect(screen.getByRole('textbox')).toHaveClass('text-right')
})

it('renders prefix icon when provided', () => {
render(<Input prefixIcon={<span data-testid="prefix-icon">Prefix</span>} />)
expect(screen.getByTestId('prefix-icon')).toBeInTheDocument()
})

it('renders suffix icon when provided', () => {
render(<Input suffixIcon={<span data-testid="suffix-icon">Suffix</span>} />)
expect(screen.getByTestId('suffix-icon')).toBeInTheDocument()
})

it('renders clear icon when clearable is true', () => {
render(<Input clearable />)
expect(screen.getByTestId('cross-2-icon')).toBeInTheDocument()
})

it('calls onClick when input is clicked', () => {
const onClick = jest.fn()
render(<Input onClick={onClick} />)
fireEvent.click(screen.getByRole('textbox'))
expect(onClick).toHaveBeenCalledTimes(1)
})

it('calls onClear when clear icon is clicked', () => {
const onClear = jest.fn()
render(<Input clearable onClear={onClear} />)
fireEvent.click(screen.getByTestId('cross-2-icon'))
expect(onClear).toHaveBeenCalledTimes(1)
})
})
2 changes: 1 addition & 1 deletion joi/src/core/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const Input = forwardRef<HTMLInputElement, Props>(
)}
{clearable && (
<div className="input__clear-icon" onClick={onClear}>
<Cross2Icon className="text-red-200" />
<Cross2Icon data-testid="cross-2-icon" className="text-red-200" />
</div>
)}
<input
Expand Down
78 changes: 78 additions & 0 deletions joi/src/core/Modal/Modal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Modal } from './index'

// Mock the styles
jest.mock('./styles.scss', () => ({}))

describe('Modal', () => {
it('renders the modal with trigger and content', () => {
render(
<Modal
trigger={<button>Open Modal</button>}
content={<div>Modal Content</div>}
/>
)

expect(screen.getByText('Open Modal')).toBeInTheDocument()
fireEvent.click(screen.getByText('Open Modal'))
expect(screen.getByText('Modal Content')).toBeInTheDocument()
})

it('renders the modal with title', () => {
render(
<Modal
trigger={<button>Open Modal</button>}
content={<div>Modal Content</div>}
title="Modal Title"
/>
)

fireEvent.click(screen.getByText('Open Modal'))
expect(screen.getByText('Modal Title')).toBeInTheDocument()
})

it('renders full page modal', () => {
render(
<Modal
trigger={<button>Open Modal</button>}
content={<div>Modal Content</div>}
fullPage
/>
)

fireEvent.click(screen.getByText('Open Modal'))
expect(screen.getByRole('dialog')).toHaveClass('modal__content--fullpage')
})

it('hides close button when hideClose is true', () => {
render(
<Modal
trigger={<button>Open Modal</button>}
content={<div>Modal Content</div>}
hideClose
/>
)

fireEvent.click(screen.getByText('Open Modal'))
expect(screen.queryByLabelText('Close')).not.toBeInTheDocument()
})

it('calls onOpenChange when opening and closing the modal', () => {
const onOpenChangeMock = jest.fn()
render(
<Modal
trigger={<button>Open Modal</button>}
content={<div>Modal Content</div>}
onOpenChange={onOpenChangeMock}
/>
)

fireEvent.click(screen.getByText('Open Modal'))
expect(onOpenChangeMock).toHaveBeenCalledWith(true)

fireEvent.click(screen.getByLabelText('Close'))
expect(onOpenChangeMock).toHaveBeenCalledWith(false)
})
})
55 changes: 55 additions & 0 deletions joi/src/core/Progress/Progress.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Progress } from './index'

// Mock the styles
jest.mock('./styles.scss', () => ({}))

describe('@joi/core/Progress', () => {
it('renders with default props', () => {
render(<Progress value={50} />)
const progressElement = screen.getByRole('progressbar')
expect(progressElement).toBeInTheDocument()
expect(progressElement).toHaveClass('progress')
expect(progressElement).toHaveClass('progress--medium')
expect(progressElement).toHaveAttribute('aria-valuenow', '50')
})

it('applies custom className', () => {
render(<Progress value={50} className="custom-class" />)
const progressElement = screen.getByRole('progressbar')
expect(progressElement).toHaveClass('custom-class')
})

it('renders with different sizes', () => {
const { rerender } = render(<Progress value={50} size="small" />)
let progressElement = screen.getByRole('progressbar')
expect(progressElement).toHaveClass('progress--small')

rerender(<Progress value={50} size="large" />)
progressElement = screen.getByRole('progressbar')
expect(progressElement).toHaveClass('progress--large')
})

it('sets the correct transform style based on value', () => {
render(<Progress value={75} />)
const progressElement = screen.getByRole('progressbar')
const indicatorElement = progressElement.firstChild as HTMLElement
expect(indicatorElement).toHaveStyle('transform: translateX(-25%)')
})

it('handles edge cases for value', () => {
const { rerender } = render(<Progress value={0} />)
let progressElement = screen.getByRole('progressbar')
let indicatorElement = progressElement.firstChild as HTMLElement
expect(indicatorElement).toHaveStyle('transform: translateX(-100%)')
expect(progressElement).toHaveAttribute('aria-valuenow', '0')

rerender(<Progress value={100} />)
progressElement = screen.getByRole('progressbar')
indicatorElement = progressElement.firstChild as HTMLElement
expect(indicatorElement).toHaveStyle('transform: translateX(-0%)')
expect(progressElement).toHaveAttribute('aria-valuenow', '100')
})
})
9 changes: 8 additions & 1 deletion joi/src/core/Progress/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ export interface ProgressProps

const Progress = ({ className, size, value, ...props }: ProgressProps) => {
return (
<div className={twMerge(progressVariants({ size, className }))} {...props}>
<div
role="progressbar"
aria-valuenow={value}
aria-valuemin={0}
aria-valuemax={100}
className={twMerge(progressVariants({ size, className }))}
{...props}
>
<div
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
className="progress--indicator"
Expand Down
47 changes: 47 additions & 0 deletions joi/src/core/ScrollArea/ScrollArea.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import { ScrollArea } from './index'

declare const global: typeof globalThis

// Mock the styles
jest.mock('./styles.scss', () => ({}))

class ResizeObserverMock {
observe() {}
unobserve() {}
disconnect() {}
}

global.ResizeObserver = ResizeObserverMock

describe('@joi/core/ScrollArea', () => {
it('renders children correctly', () => {
render(
<ScrollArea>
<div data-testid="child">Test Content</div>
</ScrollArea>
)

const child = screen.getByTestId('child')
expect(child).toBeInTheDocument()
expect(child).toHaveTextContent('Test Content')
})

it('applies custom className', () => {
const { container } = render(<ScrollArea className="custom-class" />)

const root = container.firstChild as HTMLElement
expect(root).toHaveClass('scroll-area__root')
expect(root).toHaveClass('custom-class')
})

it('forwards ref to the Viewport component', () => {
const ref = React.createRef<HTMLDivElement>()
render(<ScrollArea ref={ref} />)

expect(ref.current).toBeInstanceOf(HTMLDivElement)
expect(ref.current).toHaveClass('scroll-area__viewport')
})
})
Loading

0 comments on commit ac67247

Please sign in to comment.