Skip to content

Commit c43d6c2

Browse files
committed
test(FilePicker): Add more use cases
Signed-off-by: Louis Chmn <louis@chmn.me> [skip ci]
1 parent 16ee7d8 commit c43d6c2

File tree

1 file changed

+152
-74
lines changed

1 file changed

+152
-74
lines changed

lib/components/FilePicker/FileListRow.spec.ts

Lines changed: 152 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,108 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6+
import type { VueWrapper } from '@vue/test-utils'
7+
import type { ComponentProps } from 'vue-component-type-helpers'
8+
69
import { afterEach, describe, expect, it, vi } from 'vitest'
7-
import { File } from '@nextcloud/files'
10+
import { File, Folder, Permission } from '@nextcloud/files'
811
import { shallowMount } from '@vue/test-utils'
912

1013
import FileListRow from './FileListRow.vue'
1114
import { nextTick } from 'vue'
1215

13-
describe('FilePicker: FileListRow', () => {
14-
const node = new File({
15-
owner: null,
16-
mtime: new Date(),
17-
mime: 'text/plain',
18-
source: 'https://example.com/dav/a.txt',
19-
root: '/',
20-
attributes: { displayName: 'test' },
16+
type SubmitAction = (wrapper: VueWrapper<any>) => Promise<void>
17+
type ElementEvent = { 'update:selected': boolean | undefined, enterDirectory: Folder | undefined }
18+
19+
async function clickCheckboxAction(wrapper: VueWrapper<any>) {
20+
wrapper.find('input[type="checkbox"]').trigger('click')
21+
}
22+
23+
async function clickElementAction(wrapper: VueWrapper<any>) {
24+
wrapper.find('[data-testid="row-name"]').trigger('click')
25+
}
26+
27+
async function pressEnterAction(wrapper: VueWrapper<any>) {
28+
wrapper.element.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter' }))
29+
await nextTick()
30+
}
31+
32+
function testSubmitNode(name: string, propsData: ComponentProps<typeof FileListRow>, eventPayload: ElementEvent, actionCallback: SubmitAction) {
33+
it(name, async () => {
34+
const wrapper = shallowMount(FileListRow, {
35+
propsData,
36+
stubs: {
37+
NcCheckboxRadioSwitch: {
38+
template: '<label><input type="checkbox" @click="$emit(\'update:model-value\', true)" ></label>',
39+
},
40+
},
41+
})
42+
43+
await actionCallback(wrapper)
44+
45+
for (const [event, payload] of Object.entries(eventPayload)) {
46+
if (payload === undefined) {
47+
expect(wrapper.emitted(event)).toBeUndefined()
48+
} else {
49+
expect(wrapper.emitted(event)).toEqual([[payload]])
50+
}
51+
}
2152
})
53+
}
54+
55+
const node = new File({
56+
owner: 'alice',
57+
mtime: new Date(),
58+
mime: 'text/plain',
59+
source: 'https://example.com/remote.php/dav/alice/a.txt',
60+
root: '/',
61+
attributes: { displayName: 'test' },
62+
})
63+
64+
const folder = new Folder({
65+
owner: 'alice',
66+
mtime: new Date(),
67+
mime: 'httpd/unix-directory',
68+
source: 'https://example.com/remote.php/dav/alice/b',
69+
root: '/',
70+
permissions: Permission.ALL,
71+
attributes: { displayName: 'test folder' },
72+
})
2273

74+
const folderNonReadable = new Folder({
75+
owner: 'alice',
76+
mtime: new Date(),
77+
mime: 'httpd/unix-directory',
78+
source: 'https://example.com/remote.php/dav/alice/b',
79+
root: '/',
80+
permissions: Permission.ALL & ~Permission.READ,
81+
attributes: { displayName: 'test folder' },
82+
})
83+
84+
const defaultOptions = {
85+
selected: false,
86+
cropImagePreviews: true,
87+
canPick: true,
88+
showCheckbox: true,
89+
allowPickDirectory: true,
90+
}
91+
92+
const noEmits = {
93+
'update:selected': undefined,
94+
enterDirectory: undefined,
95+
}
96+
97+
const selectNode = {
98+
'update:selected': true,
99+
enterDirectory: undefined,
100+
}
101+
102+
const navigateToFolder = {
103+
'update:selected': undefined,
104+
enterDirectory: folder,
105+
}
106+
107+
describe('FilePicker: FileListRow', () => {
23108
afterEach(() => {
24109
vi.restoreAllMocks()
25110
})
@@ -65,80 +150,73 @@ describe('FilePicker: FileListRow', () => {
65150
expect(wrapper.find('[data-testid="row-checkbox"]').exists()).toBe(false)
66151
})
67152

68-
it('Click checkbox triggers select', async () => {
69-
const wrapper = shallowMount(FileListRow, {
70-
propsData: {
71-
allowPickDirectory: false,
72-
selected: false,
73-
showCheckbox: true,
74-
canPick: true,
75-
node,
76-
cropImagePreviews: true,
77-
},
78-
stubs: {
79-
NcCheckboxRadioSwitch: {
80-
template: '<label><input type="checkbox" @click="$emit(\'update:model-value\', true)" ></label>',
81-
},
82-
},
153+
describe('when node is a file', () => {
154+
const fileOptions = {
155+
...defaultOptions,
156+
node,
157+
}
158+
159+
testSubmitNode('Click checkbox triggers select', { ...fileOptions }, selectNode, clickCheckboxAction)
160+
testSubmitNode('Click element triggers select', { ...fileOptions }, selectNode, clickElementAction)
161+
testSubmitNode('Click element without checkbox triggers select', { ...fileOptions, showCheckbox: false }, selectNode, clickElementAction)
162+
testSubmitNode('Enter triggers select', { ...fileOptions, showCheckbox: false }, selectNode, pressEnterAction)
163+
164+
describe('canPick: false', () => {
165+
const options = {
166+
...fileOptions,
167+
canPick: false,
168+
}
169+
170+
testSubmitNode('Click checkbox does not triggers select', options, noEmits, clickCheckboxAction)
171+
testSubmitNode('Click element does not triggers select', options, noEmits, clickElementAction)
172+
testSubmitNode('Click element without checkbox does not triggers select', { ...options, showCheckbox: false }, noEmits, clickElementAction)
173+
testSubmitNode('Enter does not triggers select', { ...options, showCheckbox: false }, noEmits, pressEnterAction)
83174
})
84-
85-
await wrapper.find('input[type="checkbox"]').trigger('click')
86-
87-
// one event with payload `true` is expected
88-
expect(wrapper.emitted('update:selected')).toEqual([[true]])
89175
})
90176

91-
it('Click element triggers select', async () => {
92-
const wrapper = shallowMount(FileListRow, {
93-
propsData: {
94-
allowPickDirectory: false,
95-
selected: false,
96-
showCheckbox: true,
97-
canPick: true,
98-
node,
99-
cropImagePreviews: true,
100-
},
177+
describe('when node is a folder', () => {
178+
const folderOptions = {
179+
...defaultOptions,
180+
node: folder,
181+
}
182+
183+
testSubmitNode('Click checkbox triggers select', folderOptions, selectNode, clickCheckboxAction)
184+
testSubmitNode('Click element navigates to it', folderOptions, navigateToFolder, clickElementAction)
185+
testSubmitNode('Click element without checkbox navigates to it', { ...folderOptions, showCheckbox: false }, navigateToFolder, clickElementAction)
186+
testSubmitNode('Enter navigates to it', { ...folderOptions, showCheckbox: false }, navigateToFolder, pressEnterAction)
187+
188+
describe('canPick: false', () => {
189+
const options = {
190+
...folderOptions,
191+
canPick: false,
192+
}
193+
194+
testSubmitNode('Click checkbox does not triggers select', options, noEmits, clickCheckboxAction)
195+
testSubmitNode('Click element navigates to it', options, navigateToFolder, clickElementAction)
196+
testSubmitNode('Click element without checkbox navigates to it', { ...options, showCheckbox: false }, navigateToFolder, clickElementAction)
197+
testSubmitNode('Enter navigates to it', { ...options, showCheckbox: false }, navigateToFolder, pressEnterAction)
101198
})
102199

103-
await wrapper.find('[data-testid="row-name"]').trigger('click')
104-
105-
// one event with payload `true` is expected
106-
expect(wrapper.emitted('update:selected')).toEqual([[true]])
107-
})
200+
describe('without READ permissions', () => {
201+
const options = {
202+
...folderOptions,
203+
node: folderNonReadable,
204+
}
108205

109-
it('Click element without checkbox triggers select', async () => {
110-
const wrapper = shallowMount(FileListRow, {
111-
propsData: {
112-
allowPickDirectory: false,
113-
selected: false,
114-
showCheckbox: false,
115-
canPick: true,
116-
node,
117-
cropImagePreviews: true,
118-
},
206+
testSubmitNode('Click checkbox triggers select', options, selectNode, clickCheckboxAction)
207+
testSubmitNode('Click element does not navigates to it', options, noEmits, clickElementAction)
208+
testSubmitNode('Click element without checkbox does not navigates to it', { ...options, showCheckbox: false }, noEmits, clickElementAction)
209+
testSubmitNode('Enter does not navigates to it', { ...options, showCheckbox: false }, noEmits, pressEnterAction)
119210
})
120211

121-
await wrapper.find('[data-testid="row-name"]').trigger('click')
122-
123-
// one event with payload `true` is expected
124-
expect(wrapper.emitted('update:selected')).toEqual([[true]])
125-
})
126-
127-
it('Enter triggers select', async () => {
128-
const wrapper = shallowMount(FileListRow, {
129-
propsData: {
212+
describe('allowPickDirectory: false', () => {
213+
const options = {
214+
...folderOptions,
215+
node: folderNonReadable,
130216
allowPickDirectory: false,
131-
selected: false,
132-
showCheckbox: false,
133-
canPick: true,
134-
node,
135-
cropImagePreviews: true,
136-
},
137-
})
217+
}
138218

139-
wrapper.element.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter' }))
140-
await nextTick()
141-
142-
expect(wrapper.emitted('update:selected')).toEqual([[true]])
219+
testSubmitNode('Click checkbox does not triggers select', options, noEmits, clickCheckboxAction)
220+
})
143221
})
144222
})

0 commit comments

Comments
 (0)