Skip to content

Commit 1aa9b6b

Browse files
fix: prevent duplicate items in column selection (#1503)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 1df3966 commit 1aa9b6b

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

app/composables/usePreferencesProvider.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defu } from 'defu'
1+
import { createDefu } from 'defu'
22

33
/**
44
* Abstraction for preferences storage
@@ -13,6 +13,13 @@ interface StorageProvider<T> {
1313
remove: () => void
1414
}
1515

16+
const defu = createDefu((object, key, value) => {
17+
if (Array.isArray(object[key]) && Array.isArray(value)) {
18+
object[key] = value
19+
return true
20+
}
21+
})
22+
1623
/**
1724
* Creates a localStorage-based storage provider
1825
*/
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { describe, it, expect, beforeEach } from 'vitest'
2+
import { defineComponent, onMounted } from 'vue'
3+
import { mount } from '@vue/test-utils'
4+
import { usePreferencesProvider } from '../../../app/composables/usePreferencesProvider'
5+
6+
const STORAGE_KEY = 'npmx-list-prefs'
7+
8+
function mountWithSetup(run: () => void) {
9+
return mount(
10+
defineComponent({
11+
name: 'TestHarness',
12+
setup() {
13+
run()
14+
return () => null
15+
},
16+
}),
17+
{ attachTo: document.body },
18+
)
19+
}
20+
21+
function setLocalStorage(stored: Record<string, any>) {
22+
localStorage.setItem(STORAGE_KEY, JSON.stringify(stored))
23+
}
24+
25+
describe('usePreferencesProvider', () => {
26+
beforeEach(() => {
27+
localStorage.clear()
28+
})
29+
30+
it('initializes with default values when storage is empty', () => {
31+
mountWithSetup(() => {
32+
const defaults = { theme: 'light', cols: ['name', 'version'] }
33+
const { data } = usePreferencesProvider(defaults)
34+
onMounted(() => {
35+
expect(data.value).toEqual(defaults)
36+
})
37+
})
38+
})
39+
40+
it('loads values from localStorage', () => {
41+
mountWithSetup(() => {
42+
const defaults = { theme: 'light' }
43+
const stored = { theme: 'dark' }
44+
setLocalStorage(stored)
45+
const { data } = usePreferencesProvider(defaults)
46+
onMounted(() => {
47+
expect(data.value).toEqual(stored)
48+
})
49+
})
50+
})
51+
52+
it('handles array merging by replacement', () => {
53+
mountWithSetup(() => {
54+
const defaults = { cols: ['name', 'version', 'date'] }
55+
const stored = { cols: ['name', 'version'] }
56+
setLocalStorage(stored)
57+
const { data } = usePreferencesProvider(defaults)
58+
onMounted(() => {
59+
expect(data.value.cols).toEqual(['name', 'version'])
60+
})
61+
})
62+
})
63+
})

0 commit comments

Comments
 (0)