import { describe, test, expect, beforeEach } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { LockSelection, LOCK_SELECTION_TOOL_ID } from './lock-selection'
import { useWidgetStore } from '../../stores/widget-store'
import type { EchartWidgetData } from '../../echart/types'
import type { LockSelectionState } from './types'
import { WidgetLoader } from '../../loader/loader'
// Test data
const mockData: EchartWidgetData = [
[
{ name: 'Electronics', value: 440 },
{ name: 'Clothing', value: 280 },
{ name: 'Books', value: 100 },
],
]
describe('LockSelection', () => {
const widgetId = 'test-lock-selection'
beforeEach(() => {
useWidgetStore.getState().clearWidgets()
})
test('renders nothing when no selections', () => {
const { container } = render(
,
)
expect(container.firstChild).toBeNull()
})
test('renders lock button when there are selections', () => {
render()
const button = screen.getByRole('button')
expect(button).toBeTruthy()
})
test('shows lock tooltip when unlocked', () => {
render()
const button = screen.getByRole('button', { name: 'Lock selection' })
expect(button).toBeTruthy()
})
test('shows unlock tooltip when locked', () => {
render()
// Lock by clicking the button
const button = screen.getByRole('button')
fireEvent.click(button)
const unlockedButton = screen.getByRole('button', {
name: 'Unlock selection',
})
expect(unlockedButton).toBeTruthy()
})
test('toggles isLocked in tool state when clicked', () => {
render()
const button = screen.getByRole('button')
fireEvent.click(button)
const widget = useWidgetStore.getState().getWidget(widgetId)
const tool = widget?.registeredTools?.find(
(t) => t.id === LOCK_SELECTION_TOOL_ID,
)
expect(tool?.enabled).toBe(true)
})
test('filters data in store when locking', async () => {
const selectedItems = ['Electronics']
render(
,
)
const button = screen.getByRole('button')
fireEvent.click(button)
await useWidgetStore.getState().executeToolPipeline(widgetId, mockData)
const widget = useWidgetStore.getState().getWidget(widgetId)
expect(widget?.data).toEqual([[{ name: 'Electronics', value: 440 }]])
})
test('clears locked items when unlocking', () => {
render()
// Lock first
const button = screen.getByRole('button')
fireEvent.click(button)
// Then unlock
fireEvent.click(button)
const widget = useWidgetStore.getState().getWidget(widgetId)
const tool = widget?.registeredTools?.find(
(t) => t.id === LOCK_SELECTION_TOOL_ID,
)
expect(tool?.enabled).toBe(false)
})
test('clears lock state when selectedItems becomes empty while locked', () => {
// Simulate remount: isLocked persists in store but selectedItems is now empty
useWidgetStore
.getState()
.setWidget(widgetId, { isLocked: true, lockedItems: ['Electronics'] })
render()
const widget = useWidgetStore.getState().getWidget(widgetId)
expect((widget as LockSelectionState | undefined)?.isLocked).toBe(false)
expect((widget as LockSelectionState | undefined)?.lockedItems).toEqual([])
})
test('has active state when locked', () => {
render()
const button = screen.getByRole('button')
fireEvent.click(button)
expect(button.getAttribute('data-active')).toBe('true')
})
test('has inactive state when unlocked', () => {
render()
const button = screen.getByRole('button')
expect(button.getAttribute('data-active')).toBe('false')
})
test('uses custom labels', () => {
render(
,
)
const button = screen.getByRole('button', { name: 'Toggle lock' })
expect(button).toBeTruthy()
})
test('filters multiple series when locking', async () => {
const multiSeriesData: EchartWidgetData = [
[
{ name: 'Electronics', value: 440 },
{ name: 'Clothing', value: 280 },
],
[
{ name: 'Electronics', value: 520 },
{ name: 'Clothing', value: 350 },
],
]
const selectedItems = ['Electronics']
render(
,
)
const button = screen.getByRole('button')
fireEvent.click(button)
await useWidgetStore
.getState()
.executeToolPipeline(widgetId, multiSeriesData)
const widget = useWidgetStore.getState().getWidget(widgetId)
expect(widget?.data).toEqual([
[{ name: 'Electronics', value: 440 }],
[{ name: 'Electronics', value: 520 }],
])
})
})