diff --git a/src/components/avatar/__test__/Avatar.test.tsx b/src/components/avatar/__test__/Avatar.test.tsx
index 1bd8722..f0accdb 100644
--- a/src/components/avatar/__test__/Avatar.test.tsx
+++ b/src/components/avatar/__test__/Avatar.test.tsx
@@ -1,50 +1,72 @@
import { render } from '@testing-library/react';
-import { describe, expect, it } from 'vitest';
+import { describe, expect, it, test } from 'vitest';
import { Avatar } from '../';
+import DefaultAvatar from '../components/DefaultAvatar';
+import PictureAvatar from '../components/PictureAvatar';
const FULL_NAME = 'My Internxt';
const IMAGE_SRC = 'https://internxt.com/favicon.ico';
describe('Avatar component', () => {
- it('Avatar with full name (first letters) should render correctly', () => {
+ test('Avatar with full name (first letters) should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('Avatar with fullname as null should render correctly with empty letters', () => {
+ test('Avatar with single word name should render correctly', () => {
+ const avatarComponent = render();
+ expect(avatarComponent).toMatchSnapshot();
+ });
+
+ test('Avatar with empty spaces name should return empty content', () => {
+ const avatarComponent = render();
+ expect(avatarComponent).toMatchSnapshot();
+ });
+
+ test('Avatar with fullname as null should render correctly with empty letters', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('Avatar with avatar (user image profile) should render correctly', () => {
+ test('Avatar with avatar (user image profile) should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('XXS Avatar should render correctly', () => {
+ test('XXS Avatar should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('XS Avatar should render correctly', () => {
+ test('XS Avatar should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('SM Avatar should render correctly', () => {
+ test('SM Avatar should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('Base Avatar should render correctly', () => {
+ test('Base Avatar should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('LG Avatar should render correctly', () => {
+ test('LG Avatar should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
- it('XL Avatar should render correctly', () => {
+ test('XL Avatar should render correctly', () => {
const avatarComponent = render();
expect(avatarComponent).toMatchSnapshot();
});
+
+ test('DefaultAvatar handles default parameters', () => {
+ const avatarComponent = render();
+ expect(avatarComponent).toMatchSnapshot();
+ });
+
+ test('PictureAvatar handles default parameters', () => {
+ const avatarComponent = render();
+ expect(avatarComponent).toMatchSnapshot();
+ });
});
diff --git a/src/components/avatar/__test__/__snapshots__/Avatar.test.tsx.snap b/src/components/avatar/__test__/__snapshots__/Avatar.test.tsx.snap
index 876ffa2..ede2e30 100644
--- a/src/components/avatar/__test__/__snapshots__/Avatar.test.tsx.snap
+++ b/src/components/avatar/__test__/__snapshots__/Avatar.test.tsx.snap
@@ -75,6 +75,81 @@ exports[`Avatar component > Avatar with avatar (user image profile) should rende
}
`;
+exports[`Avatar component > Avatar with empty spaces name should return empty content 1`] = `
+{
+ "asFragment": [Function],
+ "baseElement":
+
+ ,
+ "container": ,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
+
exports[`Avatar component > Avatar with full name (first letters) should render correctly 1`] = `
{
"asFragment": [Function],
@@ -229,6 +304,85 @@ exports[`Avatar component > Avatar with fullname as null should render correctly
}
`;
+exports[`Avatar component > Avatar with single word name should render correctly 1`] = `
+{
+ "asFragment": [Function],
+ "baseElement":
+
+ ,
+ "container": ,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
+
exports[`Avatar component > Base Avatar should render correctly 1`] = `
{
"asFragment": [Function],
@@ -304,6 +458,85 @@ exports[`Avatar component > Base Avatar should render correctly 1`] = `
}
`;
+exports[`Avatar component > DefaultAvatar handles default parameters 1`] = `
+{
+ "asFragment": [Function],
+ "baseElement":
+
+ ,
+ "container": ,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
+
exports[`Avatar component > LG Avatar should render correctly 1`] = `
{
"asFragment": [Function],
@@ -379,6 +612,81 @@ exports[`Avatar component > LG Avatar should render correctly 1`] = `
}
`;
+exports[`Avatar component > PictureAvatar handles default parameters 1`] = `
+{
+ "asFragment": [Function],
+ "baseElement":
+
+

+
+ ,
+ "container":
+

+
,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
+
exports[`Avatar component > SM Avatar should render correctly 1`] = `
{
"asFragment": [Function],
diff --git a/src/components/contextMenu/__test__/ContextMenu.test.tsx b/src/components/contextMenu/__test__/ContextMenu.test.tsx
index 03f0524..b485503 100644
--- a/src/components/contextMenu/__test__/ContextMenu.test.tsx
+++ b/src/components/contextMenu/__test__/ContextMenu.test.tsx
@@ -96,4 +96,22 @@ describe('ContextMenu Component', () => {
if (menuItem && 'action' in menuItem) expect(menuItem?.action).toHaveBeenCalledWith(props.item);
expect(props.handleMenuClose).toHaveBeenCalled();
});
+
+ it('positions menu at bottom when isContextMenuCutOff is true and not from right click', () => {
+ const { container } = render(
+ ,
+ );
+ const outerDiv = container.firstChild as HTMLElement;
+ expect(outerDiv.style.bottom).toBe('40px');
+ expect(outerDiv.style.top).toBe('');
+ });
+
+ it('positions menu at top when isContextMenuCutOff is false and not from right click', () => {
+ const { container } = render(
+ ,
+ );
+ const outerDiv = container.firstChild as HTMLElement;
+ expect(outerDiv.style.top).toBe('40px');
+ expect(outerDiv.style.bottom).toBe('');
+ });
});
diff --git a/src/components/dialog/__test__/Dialog.test.tsx b/src/components/dialog/__test__/Dialog.test.tsx
index 29a017c..0901048 100644
--- a/src/components/dialog/__test__/Dialog.test.tsx
+++ b/src/components/dialog/__test__/Dialog.test.tsx
@@ -51,6 +51,27 @@ describe('Dialog', () => {
expect(defaultProps.onClose).toHaveBeenCalled();
});
+ it('does not call onClose when pressing other keys', () => {
+ renderDialog();
+ fireEvent.keyDown(window, { key: 'Enter' });
+ expect(defaultProps.onClose).not.toHaveBeenCalled();
+ });
+
+ it('handles timeouts correctly on active transition states', () => {
+ vi.useFakeTimers();
+ const { rerender } = renderDialog({ isOpen: false });
+
+ vi.runAllTimers();
+
+ rerender();
+ vi.runAllTimers();
+
+ rerender();
+ vi.runAllTimers();
+
+ vi.useRealTimers();
+ });
+
it('calls onPrimaryAction when clicking the primary button', () => {
const { getByText } = renderDialog();
fireEvent.click(getByText(defaultProps.primaryAction));
diff --git a/src/components/dropdown/__test__/Dropdown.test.tsx b/src/components/dropdown/__test__/Dropdown.test.tsx
index bfb64ad..f8ad83c 100644
--- a/src/components/dropdown/__test__/Dropdown.test.tsx
+++ b/src/components/dropdown/__test__/Dropdown.test.tsx
@@ -155,4 +155,85 @@ describe('Dropdown component', () => {
const menu = getByTestId('menu-dropdown');
expect(menu).toHaveClass('scale-95 opacity-0');
});
+
+ it('should extract padding values and open to the right', () => {
+ const { getByTestId } = render(
+
+ Dropdown
+ ,
+ );
+ const menu = getByTestId('menu-dropdown');
+ expect(menu).toHaveClass('right-0');
+ });
+
+ it('should handle undefined options and dropdownActionsContext, and render menuItems', () => {
+ const { getByRole, getByText } = render(
+ Custom Item]}>
+ Dropdown
+ ,
+ );
+
+ fireEvent.click(getByRole('button'));
+ expect(getByText('Custom Item')).toBeInTheDocument();
+ });
+
+ it('should handle children as a function', () => {
+ const { getByRole, getByText } = render(
+
+ {({ open }) => {open ? 'Close' : 'Open'}}
+ ,
+ );
+
+ expect(getByText('Open')).toBeInTheDocument();
+ fireEvent.click(getByRole('button'));
+ expect(getByText('Close')).toBeInTheDocument();
+ });
+
+ it('should close when clicking outside', () => {
+ const { getByRole, getByTestId } = renderDropdown();
+ const button = getByRole('button');
+ const menu = getByTestId('menu-dropdown');
+
+ fireEvent.click(button);
+ expect(menu).toHaveClass('opacity-100');
+
+ fireEvent.mouseDown(document.body);
+ expect(menu).toHaveClass('opacity-0');
+ });
+
+ it('should not close when mousedown fires inside the dropdown container', () => {
+ const { getByRole, getByTestId } = renderDropdown();
+ const button = getByRole('button');
+ const menu = getByTestId('menu-dropdown');
+
+ fireEvent.click(button);
+ expect(menu).toHaveClass('opacity-100');
+
+ fireEvent.mouseDown(button);
+ expect(menu).toHaveClass('opacity-100');
+ });
+
+ it('should close when right-clicking outside the dropdown', async () => {
+ const { getByRole, getByTestId } = renderDropdown();
+ const button = getByRole('button');
+ const menu = getByTestId('menu-dropdown');
+
+ fireEvent.click(button);
+ expect(menu).toHaveClass('opacity-100');
+
+ fireEvent.contextMenu(document.body);
+ await waitFor(() => expect(menu).toHaveClass('opacity-0'));
+ });
+
+ it('should render correctly when options, menuItems, and dropdownActionsContext are all undefined', () => {
+ const { getByRole, getByTestId } = render(
+
+ Dropdown
+ ,
+ );
+
+ fireEvent.click(getByRole('button'));
+ const menu = getByTestId('menu-dropdown');
+ expect(menu).toHaveClass('scale-100');
+ });
});
diff --git a/src/components/infiniteScroll/InfiniteScroll.tsx b/src/components/infiniteScroll/InfiniteScroll.tsx
index b474a92..6c75f6f 100644
--- a/src/components/infiniteScroll/InfiniteScroll.tsx
+++ b/src/components/infiniteScroll/InfiniteScroll.tsx
@@ -66,8 +66,6 @@ const InfiniteScroll = ({
if (hasMoreItems) {
handleNextPage();
setShowLoader(true);
- } else {
- setShowLoader(false);
}
}
},
diff --git a/src/components/infiniteScroll/__test__/InfiniteScroll.test.tsx b/src/components/infiniteScroll/__test__/InfiniteScroll.test.tsx
index 601982e..8389998 100644
--- a/src/components/infiniteScroll/__test__/InfiniteScroll.test.tsx
+++ b/src/components/infiniteScroll/__test__/InfiniteScroll.test.tsx
@@ -76,6 +76,27 @@ describe('InfiniteScroll Component', () => {
await waitFor(() => expect(screen.queryByTestId('loader')).not.toBeInTheDocument());
});
+ it('does not show loader when isIntersecting is true but hasMoreItems is false', async () => {
+ vi.stubGlobal(
+ 'IntersectionObserver',
+ vi.fn((callback) => ({
+ observe: () => {
+ callback([{ isIntersecting: true }]);
+ },
+ unobserve: vi.fn(),
+ disconnect: vi.fn(),
+ })),
+ );
+
+ render(
+
+ Item 1
+
+ );
+
+ await waitFor(() => expect(screen.queryByTestId('loader')).not.toBeInTheDocument());
+ });
+
it('should call handleNextPage when scrolled to the bottom', async () => {
renderInfiniteScroll();
diff --git a/src/components/input/__test__/Input.test.tsx b/src/components/input/__test__/Input.test.tsx
index b459a81..b1a4877 100644
--- a/src/components/input/__test__/Input.test.tsx
+++ b/src/components/input/__test__/Input.test.tsx
@@ -209,4 +209,14 @@ describe('Input component', () => {
const { getByText } = renderInput({ disabled: true });
expect(getByText('Test Label')).toHaveClass('text-gray-40');
});
+
+ it('should focus email input without setting selectionStart/End', () => {
+ const { getByRole } = renderInput({ variant: 'email', autofocus: true });
+ expect(getByRole('textbox')).toHaveFocus();
+ });
+
+ it('should show 0 count when maxLength is set and value is undefined', () => {
+ const { getByText } = renderInput({ maxLength: 20, value: undefined });
+ expect(getByText('0/20')).toBeInTheDocument();
+ });
});
diff --git a/src/components/list/__test__/List.test.tsx b/src/components/list/__test__/List.test.tsx
index c1f4f61..d155910 100644
--- a/src/components/list/__test__/List.test.tsx
+++ b/src/components/list/__test__/List.test.tsx
@@ -306,6 +306,15 @@ describe('List component', () => {
expect(mockOnSelectedItemsChanged).toHaveBeenCalled();
});
+ it('closes the item context menu when clicking outside the list container', () => {
+ const { getByText } = renderList();
+
+ const itemElement = getByText('Item 2');
+ fireEvent.contextMenu(itemElement);
+
+ fireEvent.mouseDown(document.body);
+ });
+
it('should toggle selection when Ctrl or Meta key is pressed', () => {
const { getByText } = renderList();
diff --git a/src/components/list/__test__/ListHeader.test.tsx b/src/components/list/__test__/ListHeader.test.tsx
index 9162b26..2a6c3c1 100644
--- a/src/components/list/__test__/ListHeader.test.tsx
+++ b/src/components/list/__test__/ListHeader.test.tsx
@@ -85,4 +85,43 @@ describe('ListHeader', () => {
expect(mockOnOrderableColumnClicked).not.toHaveBeenCalled();
});
+
+ it('renders ArrowDown when orderBy direction is DESC', () => {
+ const { container } = renderListHeader({
+ orderBy: { field: 'id', direction: 'DESC' },
+ });
+ expect(container.querySelector('svg')).toBeInTheDocument();
+ });
+
+ it('renders ArrowUp when orderBy direction is ASC', () => {
+ const { container } = renderListHeader({
+ orderBy: { field: 'id', direction: 'ASC' },
+ });
+ expect(container.querySelector('svg')).toBeInTheDocument();
+ });
+
+ it('renders columns with buttonDataCy and textDataCy attributes', () => {
+ const { container } = render(
+ ,
+ );
+ expect(container.querySelector('[data-cy="btn-data-cy"]')).toBeInTheDocument();
+ expect(container.querySelector('[data-cy="text-data-cy"]')).toBeInTheDocument();
+ });
});