diff --git a/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx b/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx new file mode 100644 index 00000000..2b7b70c3 --- /dev/null +++ b/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx @@ -0,0 +1,88 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { UnsafeRolesDialog } from '@components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx'; +import { useUnsafeRoles } from '@components/Dialog/UnsafeRolesDialog/useUnsafeRoles.ts'; + +vi.mock('@components/Dialog/UnsafeRolesDialog/useUnsafeRoles', () => ({ + useUnsafeRoles: vi.fn() +})); + +describe('UnsafeRolesDialog', () => { + const getConfirmStateMock = vi.fn(); + const toggleConfirmStateMock = vi.fn(); + const handleCloseDialogMock = vi.fn(); + const onOpenChangeMock = vi.fn(); + + beforeEach(() => { + vi.resetAllMocks(); + + getConfirmStateMock.mockReturnValue(false); + + (useUnsafeRoles as any).mockReturnValue({ + getConfirmState: getConfirmStateMock, + toggleConfirmState: toggleConfirmStateMock, + handleCloseDialog: handleCloseDialogMock + }); + }); + + it('should not render when open is false', () => { + render(); + + expect(screen.queryByTestId('dialog')).not.toBeInTheDocument(); + }); + + it('should render when open is true', () => { + render(); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect(screen.getByRole('heading')).toBeInTheDocument(); + expect(screen.getByText('Are you sure?')).toBeInTheDocument(); + expect(screen.getAllByRole('link')).length(2); + expect(screen.getByRole('checkbox')).toBeInTheDocument(); + expect(screen.getByText('Yes, I know what I\'m doing')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /dismiss/i })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument(); + }); + + it('should have disabled confirm button when checkbox is unchecked', () => { + getConfirmStateMock.mockReturnValue(false); + + render(); + + expect(screen.getByRole('button', { name: /confirm/i })).toBeDisabled(); + }); + + it('should have enabled confirm button when checkbox is checked', () => { + getConfirmStateMock.mockReturnValue(true); + + render(); + + expect(screen.getByRole('button', { name: /confirm/i })).not.toBeDisabled(); + }); + + it('should call toggleConfirmState when checkbox is clicked', () => { + render(); + + fireEvent.click(screen.getByRole('checkbox')); + + expect(toggleConfirmStateMock).toHaveBeenCalledTimes(1); + }); + + it('should call handleCloseDialog with "dismiss" when dismiss button is clicked', () => { + render(); + + fireEvent.click(screen.getByRole('button', { name: /dismiss/i })); + + expect(handleCloseDialogMock).toHaveBeenCalledWith('dismiss'); + }); + + it('should call handleCloseDialog with "confirm" when confirm button is clicked', () => { + getConfirmStateMock.mockReturnValue(true); + + render(); + + fireEvent.click(screen.getByRole('button', { name: /confirm/i })); + + expect(handleCloseDialogMock).toHaveBeenCalledWith("confirm"); + }); +}); \ No newline at end of file diff --git a/src/components/Dialog/UnsafeRolesDialog/useUnsafeRoles.test.ts b/src/components/Dialog/UnsafeRolesDialog/useUnsafeRoles.test.ts new file mode 100644 index 00000000..d575d42d --- /dev/null +++ b/src/components/Dialog/UnsafeRolesDialog/useUnsafeRoles.test.ts @@ -0,0 +1,102 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { renderHook, act } from '@testing-library/react'; +import { useUnsafeRoles } from './useUnsafeRoles.ts'; +import { useDevice } from '@core/stores/deviceStore.ts'; +import useLocalStorage from '@core/hooks/useLocalStorage.ts'; + +vi.mock('@core/stores/deviceStore', () => ({ + useDevice: vi.fn() +})); + +vi.mock('@core/hooks/useLocalStorage', () => { + return { + default: vi.fn() + }; +}); + +describe('useUnsafeRoles', () => { + const setDialogOpenMock = vi.fn(); + const setAgreedToUnsafeRolesMock = vi.fn(); + + beforeEach(() => { + vi.resetAllMocks(); + + (useDevice as any).mockReturnValue({ + setDialogOpen: setDialogOpenMock + }); + + (useLocalStorage as any).mockReturnValue([ + false, + setAgreedToUnsafeRolesMock + ]); + }); + + it('should initialize with correct default values', () => { + const { result } = renderHook(() => useUnsafeRoles()); + + expect(result.current.agreedToUnSafeRoles).toBe(false); + expect(result.current.getConfirmState()).toBe(false); + }); + + it('should toggle confirm state correctly', () => { + const { result } = renderHook(() => useUnsafeRoles()); + + act(() => { + result.current.toggleConfirmState(); + }); + + expect(result.current.getConfirmState()).toBe(true); + + act(() => { + result.current.toggleConfirmState(); + }); + + expect(result.current.getConfirmState()).toBe(false); + }); + + it('should handle dialog close with dismiss state', () => { + const { result } = renderHook(() => useUnsafeRoles()); + + act(() => { + result.current.handleCloseDialog('dismiss'); + }); + + expect(setAgreedToUnsafeRolesMock).toHaveBeenCalledWith(false); + expect(setDialogOpenMock).toHaveBeenCalledWith('unsafeRoles', false); + }); + + it('should handle dialog close with confirm state', () => { + const { result } = renderHook(() => useUnsafeRoles()); + + act(() => { + result.current.handleCloseDialog('confirm'); + }); + + expect(setAgreedToUnsafeRolesMock).toHaveBeenCalledWith(true); + expect(setDialogOpenMock).toHaveBeenCalledWith('unsafeRoles', false); + }); + + it('should maintain state consistency across multiple operations', () => { + const { result } = renderHook(() => useUnsafeRoles()); + + act(() => { + result.current.toggleConfirmState(); + }); + expect(result.current.getConfirmState()).toBe(true); + + act(() => { + result.current.handleCloseDialog('confirm'); + }); + + expect(result.current.getConfirmState()).toBe(false); + expect(setAgreedToUnsafeRolesMock).toHaveBeenCalledWith(true); + + (useLocalStorage as any).mockReturnValue([ + true, + setAgreedToUnsafeRolesMock + ]); + + const { result: newResult } = renderHook(() => useUnsafeRoles()); + expect(newResult.current.agreedToUnSafeRoles).toBe(true); + }); +}); \ No newline at end of file diff --git a/src/components/UI/Checkbox/Checkbox.test.tsx b/src/components/UI/Checkbox/Checkbox.test.tsx new file mode 100644 index 00000000..4b909f2c --- /dev/null +++ b/src/components/UI/Checkbox/Checkbox.test.tsx @@ -0,0 +1,120 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { Checkbox } from '@components/UI/Checkbox/index.tsx'; +import React from "react"; + +vi.mock('@components/UI/Label.tsx', () => ({ + Label: ({ children, className, htmlFor, id }: { children: React.ReactNode; className: string; htmlFor: string; id: string }) => ( + + ), +})); + +vi.mock('@core/utils/cn.ts', () => ({ + cn: (...args: any) => args.filter(Boolean).join(' '), +})); + +vi.mock('react', async () => { + const actual = await vi.importActual('react'); + return { + ...actual, + useId: () => 'test-id', + }; +}); + +describe('Checkbox', () => { + beforeEach(cleanup); + + it('renders unchecked by default', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + expect(checkbox).not.toBeChecked(); + expect(screen.queryByText('Check')).not.toBeInTheDocument(); + }); + + it('renders checked when checked prop is true', () => { + render(); + expect(screen.getByRole('checkbox')).toBeChecked(); + expect(screen.getByRole('presentation')).toBeInTheDocument(); + }); + + it('calls onChange when clicked', () => { + const onChange = vi.fn(); + render(); + + fireEvent.click(screen.getByRole('presentation')); + expect(onChange).toHaveBeenCalledWith(true); + + fireEvent.click(screen.getByRole('presentation')); + expect(onChange).toHaveBeenCalledWith(false); + }); + + it('uses provided id', () => { + render(); + expect(screen.getByRole('checkbox').id).toBe('custom-id'); + }); + + it('generates id when not provided', () => { + render(); + expect(screen.getByRole('checkbox').id).toBe('test-id'); + }); + + it('renders children in Label component', () => { + render(Test Label); + expect(screen.getByTestId('label-component')).toHaveTextContent('Test Label'); + }); + + it('applies custom className', () => { + const { container } = render(); + expect(container.firstChild).toHaveClass('custom-class'); + }); + + it('applies labelClassName to Label', () => { + render(Test); + expect(screen.getByTestId('label-component')).toHaveClass('label-class'); + }); + + it('disables checkbox when disabled prop is true', () => { + render(); + expect(screen.getByRole('checkbox')).toBeDisabled(); + expect(screen.getByRole('presentation')).toHaveClass('opacity-50'); + }); + + it('does not call onChange when disabled', () => { + const onChange = vi.fn(); + render(); + + fireEvent.click(screen.getByRole('presentation')); + expect(onChange).not.toHaveBeenCalled(); + }); + + it('sets required attribute when required prop is true', () => { + render(); + expect(screen.getByRole('checkbox')).toHaveAttribute('required'); + }); + + it('sets name attribute when name prop is provided', () => { + render(); + expect(screen.getByRole('checkbox')).toHaveAttribute('name', 'test-name'); + }); + + it('passes through additional props', () => { + render(); + expect(screen.getByRole('checkbox')).toHaveAttribute('data-testid', 'extra-prop'); + }); + + it('toggles checked state correctly', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + const presentation = screen.getByRole('presentation'); + + expect(checkbox).not.toBeChecked(); + + fireEvent.click(presentation); + expect(checkbox).toBeChecked(); + + fireEvent.click(presentation); + expect(checkbox).not.toBeChecked(); + }); +}); \ No newline at end of file