/**
* BulkActionBar Component Tests
*
* Tests for the BulkActionBar component that displays a floating action bar
* when items are selected in a table.
*/
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { BulkActionBar } from './BulkActionBar';
import { describe, it, expect, vi } from 'vitest';
// Mock the Button component
vi.mock('@/ui/Button', () => ({
Button: ({ children, onClick, variant, size, icon }: any) => (
),
}));
// Mock the BulkActions component
vi.mock('@/ui/BulkActions', () => ({
BulkActions: ({ selectedCount, isOpen, children }: any) => (
{children}
),
}));
describe('BulkActionBar', () => {
const defaultProps = {
selectedCount: 0,
actions: [],
onClearSelection: vi.fn(),
};
it('should not render when no items selected', () => {
render();
expect(screen.queryByTestId('bulk-actions')).toBeFalsy();
});
it('should render when items are selected', () => {
const props = {
...defaultProps,
selectedCount: 3,
};
render();
expect(screen.getByTestId('bulk-actions')).toBeTruthy();
});
it('should display selected count', () => {
const props = {
...defaultProps,
selectedCount: 5,
};
render();
expect(screen.getByTestId('bulk-actions')).toHaveAttribute('data-count', '5');
});
it('should render with single action', () => {
const props = {
...defaultProps,
selectedCount: 2,
actions: [
{
label: 'Delete',
onClick: vi.fn(),
variant: 'danger' as const,
},
],
};
render();
expect(screen.getByText('Delete')).toBeTruthy();
});
it('should render with multiple actions', () => {
const props = {
...defaultProps,
selectedCount: 3,
actions: [
{
label: 'Export',
onClick: vi.fn(),
variant: 'primary' as const,
},
{
label: 'Archive',
onClick: vi.fn(),
variant: 'secondary' as const,
},
{
label: 'Delete',
onClick: vi.fn(),
variant: 'danger' as const,
},
],
};
render();
expect(screen.getByText('Export')).toBeTruthy();
expect(screen.getByText('Archive')).toBeTruthy();
expect(screen.getByText('Delete')).toBeTruthy();
});
it('should render cancel button', () => {
const props = {
...defaultProps,
selectedCount: 2,
actions: [
{
label: 'Delete',
onClick: vi.fn(),
},
],
};
render();
expect(screen.getByText('Cancel')).toBeTruthy();
});
it('should call action onClick when clicked', () => {
const actionOnClick = vi.fn();
const props = {
...defaultProps,
selectedCount: 2,
actions: [
{
label: 'Delete',
onClick: actionOnClick,
},
],
};
render();
const deleteButton = screen.getByText('Delete');
fireEvent.click(deleteButton);
expect(actionOnClick).toHaveBeenCalled();
});
it('should call onClearSelection when cancel is clicked', () => {
const onClearSelection = vi.fn();
const props = {
...defaultProps,
selectedCount: 2,
actions: [
{
label: 'Delete',
onClick: vi.fn(),
},
],
onClearSelection,
};
render();
const cancelButton = screen.getByText('Cancel');
fireEvent.click(cancelButton);
expect(onClearSelection).toHaveBeenCalled();
});
it('should render actions with different variants', () => {
const props = {
...defaultProps,
selectedCount: 2,
actions: [
{
label: 'Primary',
onClick: vi.fn(),
variant: 'primary' as const,
},
{
label: 'Secondary',
onClick: vi.fn(),
variant: 'secondary' as const,
},
{
label: 'Danger',
onClick: vi.fn(),
variant: 'danger' as const,
},
],
};
render();
expect(screen.getByText('Primary')).toBeTruthy();
expect(screen.getByText('Secondary')).toBeTruthy();
expect(screen.getByText('Danger')).toBeTruthy();
});
it('should render actions without variant (defaults to primary)', () => {
const props = {
...defaultProps,
selectedCount: 2,
actions: [
{
label: 'Default',
onClick: vi.fn(),
},
],
};
render();
expect(screen.getByText('Default')).toBeTruthy();
});
it('should render with empty actions array', () => {
const props = {
...defaultProps,
selectedCount: 2,
actions: [],
};
render();
expect(screen.getByTestId('bulk-actions')).toBeTruthy();
expect(screen.getByText('Cancel')).toBeTruthy();
});
it('should render with large selected count', () => {
const props = {
...defaultProps,
selectedCount: 100,
actions: [
{
label: 'Delete',
onClick: vi.fn(),
},
],
};
render();
expect(screen.getByTestId('bulk-actions')).toHaveAttribute('data-count', '100');
});
});