Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions src/tests/views/FilesList/FilesListTableHeader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createTestingPinia } from '@pinia/testing'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach, describe, expect, it, vi } from 'vitest'

import FilesListTableHeader from '../../../views/FilesList/FilesListTableHeader.vue'

import { useFilesStore } from '../../../store/files.js'
import { useFilesSortingStore } from '../../../store/filesSorting.js'
import { useSelectionStore } from '../../../store/selection.js'
Expand Down Expand Up @@ -94,22 +95,29 @@ const NcCheckboxRadioSwitchStub = {
template: '<input type="checkbox" :checked="modelValue" :data-indeterminate="indeterminate" @change="$emit(\'update:modelValue\', $event.target.checked)" />',
}

function createWrapper(filesCount = 2, options: { resetFiles?: boolean, canRequestSign?: boolean } = {}) {
const filesStore = useFilesStore()
filesStore.ordered = Array.from({ length: filesCount }, (_, index) => index + 1) as typeof filesStore.ordered
if (options.resetFiles !== false) {
filesStore.files = Object.fromEntries(Array.from({ length: filesCount }, (_, index) => {
const id = index + 1
return [id, { id }]
})) as typeof filesStore.files
}
filesStore.canRequestSign = options.canRequestSign ?? true
function createWrapper(filesCount = 2, options: { canRequestSign?: boolean } = {}) {
const ordered = Array.from({ length: filesCount }, (_, index) => index + 1)
const pinia = createTestingPinia({
createSpy: vi.fn,
stubActions: (action, store) => !(
(store.$id === 'files' && action === 'canDelete')
|| (store.$id === 'selection' && ['set', 'reset'].includes(action))
),
initialState: {
files: {
ordered,
files: Object.fromEntries(ordered.map(id => [id, { id }])),
canRequestSign: options.canRequestSign ?? true,
},
},
})

return mount(FilesListTableHeader, {
props: {
nodes: Array.from({ length: filesCount }, (_, index) => ({ id: index + 1, basename: `file${index + 1}.pdf` })),
},
global: {
plugins: [pinia],
stubs: {
NcCheckboxRadioSwitch: NcCheckboxRadioSwitchStub,
FilesListTableHeaderButton: {
Expand All @@ -123,7 +131,6 @@ function createWrapper(filesCount = 2, options: { resetFiles?: boolean, canReque

describe('FilesListTableHeader.vue', () => {
beforeEach(() => {
setActivePinia(createPinia())
vi.clearAllMocks()
})

Expand Down Expand Up @@ -245,13 +252,13 @@ describe('FilesListTableHeader.vue', () => {
})

it('selects only deletable files when using select all', async () => {
const wrapper = createWrapper(3)
const filesStore = useFilesStore()
filesStore.files = {
1: { id: 1 },
2: { id: 2, requested_by: { userId: 'someone-else' } },
3: { id: 3 },
}
const wrapper = createWrapper(3, { resetFiles: false })
const stub = wrapper.findComponent(NcCheckboxRadioSwitchStub)
const selectionStore = useSelectionStore()

Expand Down
65 changes: 34 additions & 31 deletions src/tests/views/FilesList/FilesListTableHeaderButton.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createTestingPinia } from '@pinia/testing'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach, describe, expect, it, vi } from 'vitest'

import FilesListTableHeaderButton from '../../../views/FilesList/FilesListTableHeaderButton.vue'

import { useFilesSortingStore } from '../../../store/filesSorting.js'

vi.mock('@nextcloud/event-bus', () => ({
Expand Down Expand Up @@ -57,10 +58,18 @@ const NcButtonStub = {
template: '<button :class="$attrs.class" @click="$emit(\'click\')"><slot /><slot name="icon" /></button>',
}

function createWrapper(mode = 'size', name = 'Size') {
function createWrapper(mode = 'size', name = 'Size', sortingState: { sortingMode?: string, sortingDirection?: string } = {}) {
const pinia = createTestingPinia({
createSpy: vi.fn,
initialState: {
filesSorting: sortingState,
},
})

return mount(FilesListTableHeaderButton, {
props: { name, mode },
global: {
plugins: [pinia],
stubs: {
NcButton: NcButtonStub,
NcIconSvgWrapper: true,
Expand All @@ -71,7 +80,6 @@ function createWrapper(mode = 'size', name = 'Size') {

describe('FilesListTableHeaderButton.vue', () => {
beforeEach(() => {
setActivePinia(createPinia())
vi.clearAllMocks()
})

Expand All @@ -82,11 +90,10 @@ describe('FilesListTableHeaderButton.vue', () => {
})

it('computes descending state when the same column is sorted descending', () => {
const sortingStore = useFilesSortingStore()
sortingStore.sortingMode = 'size'
sortingStore.sortingDirection = 'desc'

const wrapper = createWrapper('size')
const wrapper = createWrapper('size', 'Size', {
sortingMode: 'size',
sortingDirection: 'desc',
})
expect(wrapper.vm.isAscending).toBe(false)
})

Expand All @@ -97,31 +104,29 @@ describe('FilesListTableHeaderButton.vue', () => {
})

it('triggers the store sort toggle for the current mode', async () => {
const sortingStore = useFilesSortingStore()
const spy = vi.spyOn(sortingStore, 'toggleSortBy')
const wrapper = createWrapper('size')
const sortingStore = useFilesSortingStore()

await wrapper.find('button').trigger('click')

expect(spy).toHaveBeenCalledWith('size')
expect(sortingStore.toggleSortBy).toHaveBeenCalledWith('size')
})

describe('Vue 3 sorting interactions', () => {
it('is true when the column is active and direction is asc', () => {
const sortingStore = useFilesSortingStore()
sortingStore.sortingMode = 'created_at'
sortingStore.sortingDirection = 'asc'

const wrapper = createWrapper('created_at', 'Created at')
const wrapper = createWrapper('created_at', 'Created at', {
sortingMode: 'created_at',
sortingDirection: 'asc',
})
expect(wrapper.vm.isAscending).toBe(true)
})

it('reacts when direction changes from asc to desc', async () => {
const wrapper = createWrapper('created_at', 'Created at', {
sortingMode: 'created_at',
sortingDirection: 'asc',
})
const sortingStore = useFilesSortingStore()
sortingStore.sortingMode = 'created_at'
sortingStore.sortingDirection = 'asc'

const wrapper = createWrapper('created_at', 'Created at')
expect(wrapper.vm.isAscending).toBe(true)

sortingStore.sortingDirection = 'desc'
Expand All @@ -131,10 +136,9 @@ describe('FilesListTableHeaderButton.vue', () => {
})

it('adds the active class when the column is the active sort mode', () => {
const sortingStore = useFilesSortingStore()
sortingStore.sortingMode = 'created_at'

const wrapper = createWrapper('created_at', 'Created at')
const wrapper = createWrapper('created_at', 'Created at', {
sortingMode: 'created_at',
})
expect(wrapper.find('button').classes()).toContain('files-list__column-sort-button--active')
})

Expand All @@ -145,10 +149,10 @@ describe('FilesListTableHeaderButton.vue', () => {
})

it('removes the active class when the active mode changes', async () => {
const wrapper = createWrapper('created_at', 'Created at', {
sortingMode: 'created_at',
})
const sortingStore = useFilesSortingStore()
sortingStore.sortingMode = 'created_at'

const wrapper = createWrapper('created_at', 'Created at')
expect(wrapper.find('button').classes()).toContain('files-list__column-sort-button--active')

sortingStore.sortingMode = 'status'
Expand All @@ -158,13 +162,12 @@ describe('FilesListTableHeaderButton.vue', () => {
})

it('delegates click to toggleSortBy for the provided mode', async () => {
const sortingStore = useFilesSortingStore()
const spy = vi.spyOn(sortingStore, 'toggleSortBy')
const wrapper = createWrapper('created_at', 'Created at')
const sortingStore = useFilesSortingStore()

await wrapper.find('button').trigger('click')

expect(spy).toHaveBeenCalledWith('created_at')
expect(sortingStore.toggleSortBy).toHaveBeenCalledWith('created_at')
})
})
})
Loading