mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 23:34:31 +00:00
[bugfix] Fix shift+click deselection in asset panel (#8396)
## Summary Fix shift+click range selection not properly deselecting assets when selecting a smaller range, and improve selection performance. ## Changes - **Bug Fix**: Shift+click now replaces selection with the new range instead of combining with existing selection - **Performance**: Remove unnecessary `.every()` check in `setSelection` (O(n) → O(1)) - **Tests**: Add 23 unit tests for asset selection logic ## Test Plan - [x] Click 1st asset → only 1st selected - [x] Shift+click 3rd asset → items 1-3 selected - [x] Shift+click 1st asset → only 1st selected (was broken, now fixed) - [x] All 23 new unit tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8396-bugfix-Fix-shift-click-deselection-in-asset-panel-2f76d73d3650814ca060d1e6a40cf6d4) by [Unito](https://www.unito.io)
This commit is contained in:
138
src/platform/assets/composables/useAssetSelectionStore.test.ts
Normal file
138
src/platform/assets/composables/useAssetSelectionStore.test.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { useAssetSelectionStore } from './useAssetSelectionStore'
|
||||
|
||||
describe('useAssetSelectionStore', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
})
|
||||
|
||||
describe('addToSelection', () => {
|
||||
it('adds an asset ID to the selection', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
expect(store.isSelected('asset-1')).toBe(true)
|
||||
expect(store.selectedCount).toBe(1)
|
||||
})
|
||||
|
||||
it('can add multiple IDs', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.addToSelection('asset-2')
|
||||
expect(store.selectedCount).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeFromSelection', () => {
|
||||
it('removes an asset ID from the selection', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.removeFromSelection('asset-1')
|
||||
expect(store.isSelected('asset-1')).toBe(false)
|
||||
expect(store.selectedCount).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('setSelection', () => {
|
||||
it('replaces entire selection with new IDs', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.addToSelection('asset-2')
|
||||
|
||||
store.setSelection(['asset-3', 'asset-4'])
|
||||
|
||||
expect(store.isSelected('asset-1')).toBe(false)
|
||||
expect(store.isSelected('asset-2')).toBe(false)
|
||||
expect(store.isSelected('asset-3')).toBe(true)
|
||||
expect(store.isSelected('asset-4')).toBe(true)
|
||||
expect(store.selectedCount).toBe(2)
|
||||
})
|
||||
|
||||
it('can set to empty selection', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.setSelection([])
|
||||
expect(store.selectedCount).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('clearSelection', () => {
|
||||
it('clears all selections and resets lastSelectedIndex', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.setLastSelectedIndex(5)
|
||||
|
||||
store.clearSelection()
|
||||
|
||||
expect(store.selectedCount).toBe(0)
|
||||
expect(store.lastSelectedIndex).toBe(-1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('toggleSelection', () => {
|
||||
it('adds unselected item', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.toggleSelection('asset-1')
|
||||
expect(store.isSelected('asset-1')).toBe(true)
|
||||
})
|
||||
|
||||
it('removes selected item', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.toggleSelection('asset-1')
|
||||
expect(store.isSelected('asset-1')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isSelected', () => {
|
||||
it('returns true for selected items', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
expect(store.isSelected('asset-1')).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false for unselected items', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
expect(store.isSelected('asset-1')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('setLastSelectedIndex', () => {
|
||||
it('updates lastSelectedIndex', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.setLastSelectedIndex(10)
|
||||
expect(store.lastSelectedIndex).toBe(10)
|
||||
})
|
||||
})
|
||||
|
||||
describe('reset', () => {
|
||||
it('clears selection and resets index', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.setLastSelectedIndex(5)
|
||||
|
||||
store.reset()
|
||||
|
||||
expect(store.selectedCount).toBe(0)
|
||||
expect(store.lastSelectedIndex).toBe(-1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('computed properties', () => {
|
||||
it('hasSelection returns true when items are selected', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
expect(store.hasSelection).toBe(false)
|
||||
store.addToSelection('asset-1')
|
||||
expect(store.hasSelection).toBe(true)
|
||||
})
|
||||
|
||||
it('selectedIdsArray returns array of selected IDs', () => {
|
||||
const store = useAssetSelectionStore()
|
||||
store.addToSelection('asset-1')
|
||||
store.addToSelection('asset-2')
|
||||
expect(store.selectedIdsArray).toContain('asset-1')
|
||||
expect(store.selectedIdsArray).toContain('asset-2')
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user