Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/components/buttonCircle/__test__/CircleButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,54 @@ describe('CircleButton component', () => {
const button = render(<CircleButton variant="warning" dropdown={dropdown} />);
expect(button).toMatchSnapshot();
});

it('should close dropdown when toggle is clicked while open', () => {
const TestComponent = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<CircleButton
dropdown={<div>Dropdown Content</div>}
isOpen={isOpen}
handleClose={() => setIsOpen(false)}
handleOpen={() => setIsOpen(true)}
/>
);
};
render(<TestComponent />);
const toggleButton = screen.getAllByRole('button')[1];

fireEvent.click(toggleButton);
expect(screen.getByText('Dropdown Content')).toBeInTheDocument();

fireEvent.click(toggleButton);
expect(screen.queryByText('Dropdown Content')).not.toBeInTheDocument();
});

it('should render indicator without className correctly', () => {
const indicator = { icon: <span data-testid="indicator-icon" /> };
render(<CircleButton indicator={indicator} />);
expect(screen.getByTestId('indicator-icon')).toBeInTheDocument();
});

it('should not close dropdown when clicking inside the circle button while open', () => {
const TestComponent = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<CircleButton
dropdown={<div>Dropdown Content</div>}
isOpen={isOpen}
handleClose={() => setIsOpen(false)}
handleOpen={() => setIsOpen(true)}
/>
);
};
render(<TestComponent />);
const [mainButton, toggleButton] = screen.getAllByRole('button');

fireEvent.click(toggleButton);
expect(screen.getByText('Dropdown Content')).toBeInTheDocument();

fireEvent.click(mainButton);
expect(screen.getByText('Dropdown Content')).toBeInTheDocument();
});
});
38 changes: 36 additions & 2 deletions src/components/checkbox/__test__/Checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { describe, expect, it } from 'vitest';
import { describe, expect, it, vi } from 'vitest';
import { Checkbox } from '../';
import { render } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';

describe('Checkbox component', () => {
it('Checkbox disabled and not checked should render correctly', () => {
Expand Down Expand Up @@ -33,4 +33,38 @@ describe('Checkbox component', () => {
const button = render(<Checkbox disabled={true} checked={true} indeterminate={true} />);
expect(button).toMatchSnapshot();
});

it('calls onClick when label is clicked and not disabled', () => {
const handleClick = vi.fn();
const { container } = render(<Checkbox onClick={handleClick as any} />);
const label = container.querySelector('label');
fireEvent.click(label!);
expect(handleClick).toHaveBeenCalled();
});

it('does not call onClick when disabled', () => {
const handleClick = vi.fn();
const { container } = render(<Checkbox disabled={true} onClick={handleClick as any} />);
const label = container.querySelector('label');
fireEvent.click(label!);
expect(handleClick).not.toHaveBeenCalled();
});

it('prevents default on inner div click', () => {
const { container } = render(<Checkbox />);
const div = container.querySelector('div');

const event = new MouseEvent('click', { bubbles: true, cancelable: true });
event.preventDefault = vi.fn();
fireEvent(div!, event);
expect(event.preventDefault).toHaveBeenCalled();
});

it('triggers onKeyDown handlers without errors', () => {
const { container } = render(<Checkbox />);
const label = container.querySelector('label');
const div = container.querySelector('div');
fireEvent.keyDown(label!, { key: 'Enter' });
fireEvent.keyDown(div!, { key: 'Enter' });
});
});
25 changes: 25 additions & 0 deletions src/components/list/__test__/ListItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,31 @@ describe('ListItem', () => {
expect(mockOnClickContextMenu).toHaveBeenCalled();
});

it('updates dimensions when menuItemsRef size changes', () => {
const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');

Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { configurable: true, value: 100 });
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, value: 100 });

renderListItem({ isOpen: true, selected: true });

if (originalOffsetWidth) Object.defineProperty(HTMLElement.prototype, 'offsetWidth', originalOffsetWidth);
if (originalOffsetHeight) Object.defineProperty(HTMLElement.prototype, 'offsetHeight', originalOffsetHeight);
});

it('handles contextMenu positioning near screen edges', () => {
renderListItem({ isOpen: true, selected: true });
const listItem = screen.getByText('1').closest('div');

fireEvent.contextMenu(listItem!, {
clientX: window.innerWidth + 300,
clientY: Math.max(window.innerHeight, 500) + 300
});

expect(mockOnClickContextMenu).toHaveBeenCalled();
});

it('closes the context menu when onClose is called', () => {
renderListItem({ isOpen: true });
mockOnClose();
Expand Down
14 changes: 14 additions & 0 deletions src/components/mail/tray/__test__/TrayList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,18 @@ describe('TrayList', () => {

expect(screen.getByText('John Doe')).toBeInTheDocument();
});

it('should render without onLoadMore and onMailSelected (using defaults)', () => {
render(<TrayList mails={mockMails} loading={false} />);
expect(screen.getByText('John Doe')).toBeInTheDocument();
});

it('calls default onMailSelected and onLoadMore functions safely', () => {
const { getAllByRole } = render(
<TrayList mails={mockMails} loading={false} />
);

const emailButtons = getAllByRole('button');
expect(() => fireEvent.click(emailButtons[0])).not.toThrow();
});
});
95 changes: 95 additions & 0 deletions src/components/menu/__test__/Menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,99 @@ describe('Menu Component', () => {

expect(option1).toHaveClass('bg-gray-5');
});

it('triggers onClick on node item when Enter is pressed', () => {
const nodeClick = vi.fn();
const menuWithNode: Array<MenuItemType<{ id: number; name: string }>> = [
{ node: <button onClick={nodeClick}>Node Item</button> },
];
render(<Menu {...defaultProps} menu={menuWithNode} />);
fireEvent.keyDown(document, { key: 'ArrowDown' });
fireEvent.keyDown(document, { key: 'Enter' });
expect(nodeClick).toHaveBeenCalled();
});

it('handles node item without onClick on Enter press without errors', () => {
const menuWithNode: Array<MenuItemType<{ id: number; name: string }>> = [
{ node: <span>No Click Node</span> },
];
render(<Menu {...defaultProps} menu={menuWithNode} />);
fireEvent.keyDown(document, { key: 'ArrowDown' });
fireEvent.keyDown(document, { key: 'Enter' });
expect(handleMenuClose).toHaveBeenCalled();
});

it('calls onClick handler on item click when defined', () => {
const onClickHandler = vi.fn();
const menuWithOnClick: Array<MenuItemType<{ id: number; name: string }>> = [
{ name: 'Clickable', onClick: onClickHandler },
];
const { getByText } = render(<Menu {...defaultProps} menu={menuWithOnClick} />);
fireEvent.click(getByText('Clickable'));
expect(onClickHandler).toHaveBeenCalled();
});

it('renders keyboard shortcut icon when provided', () => {
const menuWithShortcutIcon: Array<MenuItemType<{ id: number; name: string }>> = [
{
name: 'With Icon Shortcut',
action: vi.fn(),
keyboardShortcutOptions: {
keyboardShortcutIcon: MockIcon,
keyboardShortcutText: 'Ctrl+S',
},
},
];
const { getByText, getAllByTestId } = render(<Menu {...defaultProps} menu={menuWithShortcutIcon} />);
expect(getByText('Ctrl+S')).toBeInTheDocument();
expect(getAllByTestId('mock-icon').length).toBeGreaterThan(0);
});

it('renders keyboard shortcut options without text', () => {
const menuWithIconOnly: Array<MenuItemType<{ id: number; name: string }>> = [
{
name: 'Icon Only Shortcut',
action: vi.fn(),
keyboardShortcutOptions: {
keyboardShortcutIcon: MockIcon,
},
},
];
const { getByText } = render(<Menu {...defaultProps} menu={menuWithIconOnly} />);
expect(getByText('Icon Only Shortcut')).toBeInTheDocument();
});

it('handles Enter with no selection and no genericEnterKey without errors', () => {
const menuWithItem: Array<MenuItemType<{ id: number; name: string }>> = [
{ name: 'Item', action: vi.fn() },
];
render(
<Menu
item={{ id: 1, name: 'Sample' }}
menu={menuWithItem}
isOpen={true}
handleMenuClose={handleMenuClose}
/>,
);
fireEvent.keyDown(document, { key: 'Enter' });
expect(handleMenuClose).toHaveBeenCalled();
});

it('returns null from ArrowUp when all items are unclickable', () => {
const allDisabledMenu: Array<MenuItemType<{ id: number; name: string }>> = [
{ separator: true },
{ name: 'Disabled', disabled: () => true },
];
render(<Menu {...defaultProps} menu={allDisabledMenu} />);
fireEvent.keyDown(document, { key: 'ArrowUp' });
});

it('returns null from ArrowDown when all items are unclickable', () => {
const allDisabledMenu: Array<MenuItemType<{ id: number; name: string }>> = [
{ separator: true },
{ name: 'Disabled', disabled: () => true },
];
render(<Menu {...defaultProps} menu={allDisabledMenu} />);
fireEvent.keyDown(document, { key: 'ArrowDown' });
});
});
Loading