import { describe, test, vi, expect, beforeEach } from 'vitest'
import { render, screen, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { LassoToolsInlineUI } from './lasso-tool-inline'
import { DEFAULT_LASSO_TOOLS_MODES_MAPPING } from './const'
import type { LassoToolsModes } from '../types'
import {
changeLassoToolsModeOptions,
DEFAULT_LASSO_TOOLS_MODES,
} from '../../../tests/config'
type LassoToolsMode = 'polygon' | 'rectangle' | 'circle' | 'lasso' | 'edit'
describe('LassoToolsInlineUI', () => {
const mockOnChangeMode = vi.fn()
const mockOnChipToggle = vi.fn()
const mockOnDelete = vi.fn()
const mockOnAllChipToggle = vi.fn()
const mockOnAllDelete = vi.fn()
beforeEach(() => {
vi.clearAllMocks()
})
for (const [mode, label] of Object.entries(changeLassoToolsModeOptions)) {
test(`should change mode to ${label}`, async () => {
const { container } = render(
,
)
const modeButton = within(container).getByLabelText(mode)
await userEvent.click(modeButton)
expect(mockOnChangeMode).toHaveBeenCalled()
})
}
test('should change polygons visibility when clicking on the chip', async () => {
const { container } = render(
,
)
const chip = within(container).getAllByLabelText('Show drawing')[0]!
await userEvent.click(chip)
expect(mockOnChipToggle).toHaveBeenCalledWith('polygon-id-1', true)
})
test('should remove a polygon when clicking on chip-cancel-icon', async () => {
render(
,
)
const cancelButton = screen.getAllByTestId('CancelIcon')[0]!
await userEvent.click(cancelButton)
expect(mockOnDelete).toHaveBeenCalledWith('polygon-id-1')
})
test('should change polygons visibility when clicking on Show/Hide All', async () => {
const { container } = render(
,
)
const showAllButton = within(container).getByText('Show all')
await userEvent.click(showAllButton)
expect(mockOnAllChipToggle).toHaveBeenCalled()
})
test('should remove all polygons when clicking on Delete All', async () => {
const { container } = render(
,
)
const deleteAllButton = within(container).getByText('Remove all')
await userEvent.click(deleteAllButton)
expect(mockOnAllDelete).toHaveBeenCalled()
})
})
// Aux
interface ComponentProps {
enabled: boolean
modeSelected: LassoToolsMode
mockOnChangeMode: () => void
mockOnChipToggle: () => void
mockOnDelete: () => void
mockOnAllChipToggle: () => void
mockOnAllDelete: () => void
}
describe('LassoToolsInlineUI branches', () => {
const mockOnChipToggle = vi.fn()
const mockOnDelete = vi.fn()
const mockOnAllChipToggle = vi.fn()
const mockOnAllDelete = vi.fn()
const mockOnChangeMode = vi.fn()
const requiredCallbacks = {
onChangeMode: mockOnChangeMode,
onAllChipToggle: mockOnAllChipToggle,
onAllDelete: mockOnAllDelete,
}
beforeEach(() => {
vi.clearAllMocks()
})
test('renders empty-state NoData when there are no values', () => {
const { container } = render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
)
// The "no data" Typography branch should have rendered
expect(container.querySelector('.inline')).toBeDefined()
})
test('renders without onChangeMode prop (optional callback)', async () => {
const { container } = render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
)
// Clicking the mode should not throw despite missing onChangeMode
const modeButton = within(container).getByLabelText('rectangle')
await expect(userEvent.click(modeButton)).resolves.toBeUndefined()
})
test('uses the first mode when modeSelected is not in the modes map', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
// bogus mode → modeExists=false → falls back to first key
modeSelected={'not-a-mode' as never}
onChipToggle={mockOnChipToggle}
{...requiredCallbacks}
onDelete={mockOnDelete}
/>,
),
).not.toThrow()
})
test('renders with modeSelectedValue=null when disabled (enabled=false)', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
{...requiredCallbacks}
onDelete={mockOnDelete}
/>,
),
).not.toThrow()
})
test('Actions block is hidden when there is only one value (Actions returns null branch)', () => {
const { container } = render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
)
// With ≤1 values, the "Show all / Delete all" buttons should not render
expect(within(container).queryByText(/Show all/i)).toBeNull()
expect(within(container).queryByText(/Delete all/i)).toBeNull()
})
test('uses custom labels.actions when provided', () => {
const { container } = render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
labels={{
actions: {
toggleAll: {
active: 'Hide everything',
inactive: 'Show all (custom)',
},
deleteAll: 'Wipe everything',
},
}}
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
)
expect(within(container).queryByText('Show all (custom)')).not.toBeNull()
expect(within(container).queryByText('Wipe everything')).not.toBeNull()
})
test('renders a single mode without the ModeList title (data.length <= 1)', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
{...requiredCallbacks}
onDelete={mockOnDelete}
/>,
),
).not.toThrow()
})
})
const Component = ({
enabled,
modeSelected,
mockOnChangeMode,
mockOnChipToggle,
mockOnDelete,
mockOnAllChipToggle,
mockOnAllDelete,
}: ComponentProps) => {
return (
>
}
modeSelected={modeSelected}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
onChangeMode={mockOnChangeMode}
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
onAllChipToggle={mockOnAllChipToggle}
onAllDelete={mockOnAllDelete}
/>
)
}