Skip to content

Commit 1a3b6fb

Browse files
test(vue3): add VirtualList coverage
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent ea79f45 commit 1a3b6fb

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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+
import { markRaw } from 'vue'
9+
10+
import VirtualList from '../../../views/FilesList/VirtualList.vue'
11+
12+
const filesStoreMock = {
13+
loading: false,
14+
getAllFiles: vi.fn(),
15+
filesSorted: vi.fn(() => [] as Array<{ id: number, name: string }>),
16+
}
17+
18+
const userConfigStoreMock = {
19+
files_list_grid_view: false,
20+
}
21+
22+
const subscribeMock = vi.fn()
23+
const unsubscribeMock = vi.fn()
24+
25+
class IntersectionObserverMock {
26+
observe = vi.fn()
27+
disconnect = vi.fn()
28+
29+
constructor(public callback: IntersectionObserverCallback) {}
30+
}
31+
32+
vi.mock('@nextcloud/l10n', () => ({
33+
t: vi.fn((_app: string, text: string) => text),
34+
translate: vi.fn((_app: string, text: string) => text),
35+
translatePlural: vi.fn((_app: string, singular: string, plural: string, count: number) => (count === 1 ? singular : plural)),
36+
n: vi.fn((_app: string, singular: string, plural: string, count: number) => (count === 1 ? singular : plural)),
37+
getLanguage: vi.fn(() => 'en'),
38+
getLocale: vi.fn(() => 'en'),
39+
isRTL: vi.fn(() => false),
40+
}))
41+
42+
vi.mock('debounce', () => ({
43+
default: vi.fn((fn: (...args: unknown[]) => unknown) => fn),
44+
}))
45+
46+
vi.mock('@nextcloud/event-bus', () => ({
47+
subscribe: vi.fn((...args: unknown[]) => subscribeMock(...args)),
48+
unsubscribe: vi.fn((...args: unknown[]) => unsubscribeMock(...args)),
49+
}))
50+
51+
vi.mock('../../../store/files.js', () => ({
52+
useFilesStore: vi.fn(() => filesStoreMock),
53+
}))
54+
55+
vi.mock('../../../store/userconfig.js', () => ({
56+
useUserConfigStore: vi.fn(() => userConfigStoreMock),
57+
}))
58+
59+
describe('VirtualList.vue', () => {
60+
beforeEach(() => {
61+
vi.clearAllMocks()
62+
filesStoreMock.loading = false
63+
filesStoreMock.getAllFiles.mockReset()
64+
filesStoreMock.filesSorted.mockReturnValue([])
65+
userConfigStoreMock.files_list_grid_view = false
66+
globalThis.IntersectionObserver = IntersectionObserverMock as unknown as typeof IntersectionObserver
67+
})
68+
69+
function createWrapper() {
70+
return mount(VirtualList, {
71+
props: {
72+
dataComponent: markRaw({
73+
name: 'RowComponent',
74+
props: ['source', 'loading'],
75+
template: '<tr class="row-component"><td>{{ source.name }}</td></tr>',
76+
}),
77+
loading: false,
78+
caption: 'Files table',
79+
},
80+
global: {
81+
stubs: {
82+
transition: false,
83+
},
84+
},
85+
slots: {
86+
empty: '<div class="empty-slot">Nothing here</div>',
87+
header: '<tr class="header-slot"><th>Name</th></tr>',
88+
footer: '<tr class="footer-slot"><td>Footer</td></tr>',
89+
},
90+
})
91+
}
92+
93+
it('renders the empty slot when there are no files', () => {
94+
const wrapper = createWrapper()
95+
96+
expect(wrapper.find('.files-list__empty').exists()).toBe(true)
97+
expect(wrapper.find('.empty-slot').text()).toBe('Nothing here')
98+
expect(wrapper.find('.files-list__table').classes()).toContain('files-list__table--hidden')
99+
})
100+
101+
it('renders rows and grid body class when files exist in grid mode', () => {
102+
filesStoreMock.filesSorted.mockReturnValue([
103+
{ id: 1, name: 'first.pdf' },
104+
{ id: 2, name: 'second.pdf' },
105+
])
106+
userConfigStoreMock.files_list_grid_view = true
107+
const wrapper = createWrapper()
108+
109+
expect(wrapper.findAll('.row-component')).toHaveLength(2)
110+
expect(wrapper.find('.files-list').classes()).toContain('files-list--grid')
111+
expect(wrapper.find('.files-list__tbody').classes()).toContain('files-list__tbody--grid')
112+
})
113+
114+
it('loads more files immediately when not currently loading', () => {
115+
const wrapper = createWrapper()
116+
117+
wrapper.vm.getFilesIfNotLoading()
118+
119+
expect(filesStoreMock.getAllFiles).toHaveBeenCalledTimes(1)
120+
})
121+
})

0 commit comments

Comments
 (0)