import { describe, test, vi, expect, beforeEach } from 'vitest'
import { render, screen, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { LassoToolsUI } from './lasso-tool'
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('LassoToolsUI', () => {
const mockOnActionToggle = vi.fn()
const mockOnChangeMode = vi.fn()
const mockOnChipToggle = vi.fn()
const mockOnDelete = vi.fn()
const mockOnAllChipToggle = vi.fn()
const mockOnAllDelete = vi.fn()
beforeEach(() => {
vi.clearAllMocks()
})
test('should enable drawing', async () => {
const { container } = render(
,
)
const polygonButton = within(container).getByLabelText(
'Click on the map to draw your spatial filter',
)
await userEvent.click(polygonButton)
expect(mockOnActionToggle).toHaveBeenCalledWith(true)
})
for (const [mode, label] of Object.entries(changeLassoToolsModeOptions)) {
test(`should change mode to ${label}`, async () => {
const { container } = render(
,
)
const dropdownButton = within(container).getAllByRole('button')[1]!
await userEvent.click(dropdownButton)
const modeButton = screen.getByText(label)
await userEvent.click(modeButton)
expect(mockOnChangeMode).toHaveBeenCalledWith(mode)
})
}
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 () => {
render(
,
)
const optionsButton = screen.getByTestId('MoreVertOutlinedIcon')
await userEvent.click(optionsButton)
const showAllButton = await screen.findByRole('menuitem', {
name: 'Show all',
})
await userEvent.click(showAllButton)
expect(mockOnAllChipToggle).toHaveBeenCalled()
})
test('should remove all polygons when clicking on Delete All', async () => {
render(
,
)
const optionsButton = screen.getByTestId('MoreVertOutlinedIcon')
await userEvent.click(optionsButton)
const deleteAllButton = await screen.findByRole('menuitem', {
name: 'Remove all',
})
await userEvent.click(deleteAllButton)
expect(mockOnAllDelete).toHaveBeenCalled()
})
})
describe('LassoToolsUI branches', () => {
const mockOnChipToggle = vi.fn()
const mockOnDelete = vi.fn()
const mockOnAllChipToggle = vi.fn()
const mockOnAllDelete = vi.fn()
const mockOnActionToggle = vi.fn()
const mockOnChangeMode = vi.fn()
// Required-callback overrides that satisfy the type. Each test below
// spreads this to pin down the prop set without breaking strict typing.
const requiredCallbacks = {
onActionToggle: mockOnActionToggle,
onChangeMode: mockOnChangeMode,
onAllChipToggle: mockOnAllChipToggle,
onAllDelete: mockOnAllDelete,
}
beforeEach(() => {
vi.clearAllMocks()
})
test('renders empty-state when no values', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
),
).not.toThrow()
})
test('renders with enabled=false (modeSelectedValue=null branch)', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
),
).not.toThrow()
})
test('falls back to first mode when modeSelected is unknown', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected={'unknown' as never}
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
),
).not.toThrow()
})
test('renders without onActionToggle / onChangeMode (optional callbacks)', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
),
).not.toThrow()
})
test('hides SecondaryActions when there is only one value', () => {
const { container } = render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
)
// SecondaryActions slot should not render its menu trigger
expect(within(container).queryByLabelText('More')).toBeNull()
})
test('applies custom PaperProps.sx override', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
PaperProps={
{ sx: { backgroundColor: 'red' }, 'data-x': 'y' } as never
}
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
),
).not.toThrow()
})
test('renders with custom labels.action / labels.options overrides', () => {
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
labels={
{
action: { enable: 'On', disable: 'Off' },
options: { mode: { title: 'Pick mode' } },
} as never
}
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
/>,
),
).not.toThrow()
})
test('renders an action toggle when onActionToggle is provided', () => {
const onActionToggle = vi.fn()
expect(() =>
render(
>
}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
modeSelected='polygon'
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
{...requiredCallbacks}
onActionToggle={onActionToggle}
/>,
),
).not.toThrow()
})
})
// Aux
interface ComponentProps {
enabled: boolean
modeSelected: LassoToolsMode
mockOnActionToggle: () => void
mockOnChangeMode: () => void
mockOnChipToggle: () => void
mockOnDelete: () => void
mockOnAllChipToggle: () => void
mockOnAllDelete: () => void
}
const Component = ({
enabled,
modeSelected,
mockOnActionToggle,
mockOnChangeMode,
mockOnChipToggle,
mockOnDelete,
mockOnAllChipToggle,
mockOnAllDelete,
}: ComponentProps) => {
return (
>
}
modeSelected={modeSelected}
modesMapping={DEFAULT_LASSO_TOOLS_MODES_MAPPING}
onActionToggle={mockOnActionToggle}
onChangeMode={mockOnChangeMode}
onChipToggle={mockOnChipToggle}
onDelete={mockOnDelete}
onAllChipToggle={mockOnAllChipToggle}
onAllDelete={mockOnAllDelete}
/>
)
}