Skip to content

Commit 92074a6

Browse files
committed
test: update src/tests/views/FilesList/FileEntry/FileEntryCheckbox.spec.ts
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent f71397c commit 92074a6

1 file changed

Lines changed: 188 additions & 0 deletions

File tree

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { beforeEach, describe, expect, it, vi } from 'vitest'
7+
import { mount } from '@vue/test-utils'
8+
9+
import FileEntryCheckbox from '../../../../views/FilesList/FileEntry/FileEntryCheckbox.vue'
10+
11+
const filesStoreMock = {
12+
ordered: [1, 2, 3, 4],
13+
}
14+
15+
const keyboardStoreMock = {
16+
shiftKey: false,
17+
}
18+
19+
const selectionStoreMock = {
20+
selected: [] as Array<number | string>,
21+
lastSelectedIndex: null as number | null,
22+
lastSelection: [] as Array<number | string>,
23+
set: vi.fn(),
24+
setLastIndex: vi.fn(),
25+
reset: vi.fn(),
26+
}
27+
28+
vi.mock('@nextcloud/l10n', () => ({
29+
t: vi.fn((_app: string, text: string, params?: Record<string, string>) => {
30+
if (!params) {
31+
return text
32+
}
33+
34+
return Object.entries(params).reduce((message, [key, value]) => {
35+
return message.replace(`{${key}}`, value)
36+
}, text)
37+
}),
38+
translate: vi.fn((_app: string, text: string) => text),
39+
translatePlural: vi.fn((_app: string, singular: string, plural: string, count: number) => (count === 1 ? singular : plural)),
40+
n: vi.fn((_app: string, singular: string, plural: string, count: number) => (count === 1 ? singular : plural)),
41+
getLanguage: vi.fn(() => 'en'),
42+
getLocale: vi.fn(() => 'en'),
43+
isRTL: vi.fn(() => false),
44+
}))
45+
46+
vi.mock('../../../../logger.js', () => ({
47+
default: {
48+
debug: vi.fn(),
49+
},
50+
}))
51+
52+
vi.mock('../../../../store/files.js', () => ({
53+
useFilesStore: vi.fn(() => filesStoreMock),
54+
}))
55+
56+
vi.mock('../../../../store/keyboard.js', () => ({
57+
useKeyboardStore: vi.fn(() => keyboardStoreMock),
58+
}))
59+
60+
vi.mock('../../../../store/selection.js', () => ({
61+
useSelectionStore: vi.fn(() => selectionStoreMock),
62+
}))
63+
64+
const NcCheckboxRadioSwitchStub = {
65+
name: 'NcCheckboxRadioSwitch',
66+
props: {
67+
modelValue: {
68+
type: Boolean,
69+
default: false,
70+
},
71+
ariaLabel: String,
72+
},
73+
emits: ['update:modelValue'],
74+
template: '<input type="checkbox" :checked="modelValue" :aria-label="ariaLabel" @change="$emit(\'update:modelValue\', $event.target.checked)" />',
75+
}
76+
77+
const NcLoadingIconStub = {
78+
name: 'NcLoadingIcon',
79+
props: ['name'],
80+
template: '<span class="loading-icon" />',
81+
}
82+
83+
function createWrapper(overrides: Record<string, unknown> = {}) {
84+
return mount(FileEntryCheckbox, {
85+
props: {
86+
source: {
87+
id: 3,
88+
basename: 'contract.pdf',
89+
},
90+
...overrides,
91+
},
92+
global: {
93+
stubs: {
94+
NcLoadingIcon: NcLoadingIconStub,
95+
NcCheckboxRadioSwitch: NcCheckboxRadioSwitchStub,
96+
},
97+
},
98+
})
99+
}
100+
101+
describe('FileEntryCheckbox.vue', () => {
102+
beforeEach(() => {
103+
filesStoreMock.ordered = [1, 2, 3, 4]
104+
keyboardStoreMock.shiftKey = false
105+
selectionStoreMock.selected = []
106+
selectionStoreMock.lastSelectedIndex = null
107+
selectionStoreMock.lastSelection = []
108+
selectionStoreMock.set.mockReset()
109+
selectionStoreMock.setLastIndex.mockReset()
110+
selectionStoreMock.reset.mockReset()
111+
})
112+
113+
it('computes aria label from the source basename', () => {
114+
const wrapper = createWrapper()
115+
116+
expect(wrapper.vm.ariaLabel).toBe('Toggle selection for file "contract.pdf"')
117+
})
118+
119+
it('adds the file id to the selection on a regular selection change', () => {
120+
const wrapper = createWrapper()
121+
122+
wrapper.vm.onSelectionChange(true)
123+
124+
expect(selectionStoreMock.set).toHaveBeenCalledWith([3])
125+
expect(selectionStoreMock.setLastIndex).toHaveBeenCalledWith(2)
126+
})
127+
128+
it('extends the selection range when shift is pressed', () => {
129+
keyboardStoreMock.shiftKey = true
130+
selectionStoreMock.lastSelectedIndex = 1
131+
selectionStoreMock.lastSelection = [2]
132+
const wrapper = createWrapper()
133+
134+
wrapper.vm.onSelectionChange(true)
135+
136+
expect(selectionStoreMock.set).toHaveBeenCalledWith([2, 3])
137+
expect(selectionStoreMock.setLastIndex).not.toHaveBeenCalled()
138+
})
139+
140+
it('resets the selection when escape is handled', () => {
141+
const wrapper = createWrapper()
142+
143+
wrapper.vm.resetSelection()
144+
145+
expect(selectionStoreMock.reset).toHaveBeenCalledTimes(1)
146+
})
147+
148+
describe('Vue 3 checkbox bindings', () => {
149+
it('renders an unchecked checkbox when the file is not selected', () => {
150+
const wrapper = createWrapper()
151+
const checkbox = wrapper.find('input[type="checkbox"]')
152+
153+
expect(checkbox.exists()).toBe(true)
154+
expect((checkbox.element as HTMLInputElement).checked).toBe(false)
155+
})
156+
157+
it('passes modelValue to NcCheckboxRadioSwitch', () => {
158+
const wrapper = createWrapper()
159+
const stub = wrapper.findComponent(NcCheckboxRadioSwitchStub)
160+
161+
expect(stub.props('modelValue')).toBe(false)
162+
})
163+
164+
it('handles update:modelValue emitted by the checkbox stub', async () => {
165+
const wrapper = createWrapper()
166+
const stub = wrapper.findComponent(NcCheckboxRadioSwitchStub)
167+
168+
await stub.vm.$emit('update:modelValue', true)
169+
170+
expect(selectionStoreMock.set).toHaveBeenCalledWith([3])
171+
expect(selectionStoreMock.setLastIndex).toHaveBeenCalledWith(2)
172+
})
173+
174+
it('shows the loading icon instead of the checkbox while loading', () => {
175+
const wrapper = createWrapper({ isLoading: true })
176+
177+
expect(wrapper.find('.loading-icon').exists()).toBe(true)
178+
expect(wrapper.findComponent(NcCheckboxRadioSwitchStub).exists()).toBe(false)
179+
})
180+
181+
it('shows the checkbox when loading is false', () => {
182+
const wrapper = createWrapper({ isLoading: false })
183+
184+
expect(wrapper.find('.loading-icon').exists()).toBe(false)
185+
expect(wrapper.findComponent(NcCheckboxRadioSwitchStub).exists()).toBe(true)
186+
})
187+
})
188+
})

0 commit comments

Comments
 (0)