Skip to content

Commit 047c3e4

Browse files
test(vue3): add FilesListVirtual coverage
1 parent 05223f8 commit 047c3e4

1 file changed

Lines changed: 155 additions & 0 deletions

File tree

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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 FilesListVirtual from '../../../views/FilesList/FilesListVirtual.vue'
10+
11+
const filesStoreMock = {}
12+
const selectionStoreMock = {
13+
selected: [] as Array<{ id: number }>,
14+
}
15+
const userConfigStoreMock = {
16+
files_list_grid_view: false,
17+
}
18+
19+
vi.mock('@nextcloud/l10n', () => ({
20+
t: vi.fn((_app: string, text: string) => text),
21+
n: vi.fn((_app: string, singular: string, plural: string, count: number, params?: Record<string, number>) => {
22+
const template = count === 1 ? singular : plural
23+
return template.replace('{count}', String(params?.count ?? count))
24+
}),
25+
}))
26+
27+
vi.mock('../../../store/files.js', () => ({
28+
useFilesStore: vi.fn(() => filesStoreMock),
29+
}))
30+
31+
vi.mock('../../../store/selection.js', () => ({
32+
useSelectionStore: vi.fn(() => selectionStoreMock),
33+
}))
34+
35+
vi.mock('../../../store/userconfig.js', () => ({
36+
useUserConfigStore: vi.fn(() => userConfigStoreMock),
37+
}))
38+
39+
vi.mock('../../../views/FilesList/FileEntry/FileEntry.vue', () => ({
40+
default: {
41+
name: 'FileEntry',
42+
template: '<div class="file-entry-stub" />',
43+
},
44+
}))
45+
46+
vi.mock('../../../views/FilesList/FileEntry/FileEntryGrid.vue', () => ({
47+
default: {
48+
name: 'FileEntryGrid',
49+
template: '<div class="file-entry-grid-stub" />',
50+
},
51+
}))
52+
53+
vi.mock('../../../views/FilesList/FileListFilter/FileListFilterChips.vue', () => ({
54+
default: {
55+
name: 'FileListFilterChips',
56+
template: '<div class="file-list-filter-chips-stub" />',
57+
},
58+
}))
59+
60+
vi.mock('../../../views/FilesList/FilesListTableFooter.vue', () => ({
61+
default: {
62+
name: 'FilesListTableFooter',
63+
template: '<div class="files-list-table-footer-stub" />',
64+
},
65+
}))
66+
67+
vi.mock('../../../views/FilesList/FilesListTableHeader.vue', () => ({
68+
default: {
69+
name: 'FilesListTableHeader',
70+
props: ['nodes'],
71+
template: '<div class="files-list-table-header-stub">{{ nodes.length }}</div>',
72+
},
73+
}))
74+
75+
vi.mock('../../../views/FilesList/FilesListTableHeaderActions.vue', () => ({
76+
default: {
77+
name: 'FilesListTableHeaderActions',
78+
template: '<div class="files-list-table-header-actions-stub" />',
79+
},
80+
}))
81+
82+
vi.mock('../../../views/FilesList/VirtualList.vue', () => ({
83+
default: {
84+
name: 'VirtualList',
85+
props: ['dataComponent', 'loading', 'caption'],
86+
template: `
87+
<div class="virtual-list-stub"
88+
:data-component="dataComponent?.name"
89+
:data-loading="String(loading)"
90+
:data-caption="caption">
91+
<div class="filters-slot"><slot name="filters" /></div>
92+
<div class="header-overlay-slot"><slot name="header-overlay" /></div>
93+
<div class="header-slot"><slot name="header" /></div>
94+
<div class="empty-slot"><slot name="empty" /></div>
95+
<div class="footer-slot"><slot name="footer" /></div>
96+
</div>
97+
`,
98+
},
99+
}))
100+
101+
describe('FilesListVirtual.vue', () => {
102+
const nodes = [{ id: 1, basename: 'contract.pdf' }]
103+
104+
const createWrapper = () => mount(FilesListVirtual, {
105+
props: {
106+
nodes,
107+
loading: false,
108+
},
109+
slots: {
110+
empty: '<div class="empty-content">Nothing here</div>',
111+
},
112+
})
113+
114+
beforeEach(() => {
115+
selectionStoreMock.selected = []
116+
userConfigStoreMock.files_list_grid_view = false
117+
})
118+
119+
it('renders the table row component when grid view is disabled', () => {
120+
const wrapper = createWrapper()
121+
122+
expect(wrapper.find('.virtual-list-stub').attributes('data-component')).toBe('FileEntry')
123+
expect(wrapper.vm.selectedNodes).toEqual([])
124+
expect(wrapper.vm.isNoneSelected).toBe(true)
125+
})
126+
127+
it('renders the grid row component when grid view is enabled', () => {
128+
userConfigStoreMock.files_list_grid_view = true
129+
130+
const wrapper = createWrapper()
131+
132+
expect(wrapper.find('.virtual-list-stub').attributes('data-component')).toBe('FileEntryGrid')
133+
})
134+
135+
it('shows the header overlay when files are selected', () => {
136+
selectionStoreMock.selected = [{ id: 7 }, { id: 8 }]
137+
138+
const wrapper = createWrapper()
139+
140+
expect(wrapper.vm.selectedNodes).toHaveLength(2)
141+
expect(wrapper.find('.files-list__selected').text()).toContain('selected')
142+
expect(wrapper.find('.files-list-table-header-actions-stub').exists()).toBe(true)
143+
})
144+
145+
it('passes caption, header, footer, and empty slots to VirtualList', () => {
146+
const wrapper = createWrapper()
147+
148+
expect(wrapper.vm.caption).toBe('List of files. Column headers with buttons are sortable.')
149+
expect(wrapper.find('.virtual-list-stub').attributes('data-caption')).toBe(wrapper.vm.caption)
150+
expect(wrapper.find('.files-list-table-header-stub').text()).toBe('1')
151+
expect(wrapper.find('.files-list-table-footer-stub').exists()).toBe(true)
152+
expect(wrapper.find('.file-list-filter-chips-stub').exists()).toBe(true)
153+
expect(wrapper.find('.empty-content').text()).toBe('Nothing here')
154+
})
155+
})

0 commit comments

Comments
 (0)