aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2024-08-26 20:30:26 +0200
committerGitHub <noreply@github.com>2024-08-26 20:30:26 +0200
commit4fcf4dba02a57a7e50b30efccdd9c60eca64bd16 (patch)
tree21f48a4a38cfa5c8150a8720479f0b66fd99195c /apps/files/src
parent6d31abdfd504574bf8502000c35c30becd341e61 (diff)
parent30d090fb789e62418efdfac9391518eb047ceb2b (diff)
downloadnextcloud-server-4fcf4dba02a57a7e50b30efccdd9c60eca64bd16.tar.gz
nextcloud-server-4fcf4dba02a57a7e50b30efccdd9c60eca64bd16.zip
Merge pull request #47466 from nextcloud/chore/migrate-vitest
test: Migrate from Jest to vitest
Diffstat (limited to 'apps/files/src')
-rw-r--r--apps/files/src/actions/deleteAction.spec.ts59
-rw-r--r--apps/files/src/actions/downloadAction.spec.ts12
-rw-r--r--apps/files/src/actions/editLocallyAction.spec.ts67
-rw-r--r--apps/files/src/actions/favoriteAction.spec.ts61
-rw-r--r--apps/files/src/actions/openFolderAction.spec.ts10
-rw-r--r--apps/files/src/actions/openInFilesAction.spec.ts6
-rw-r--r--apps/files/src/actions/renameAction.spec.ts8
-rw-r--r--apps/files/src/actions/sidebarAction.spec.ts12
-rw-r--r--apps/files/src/actions/viewInFolderAction.spec.ts14
-rw-r--r--apps/files/src/composables/useNavigation.spec.ts9
-rw-r--r--apps/files/src/services/DropServiceUtils.spec.ts17
-rw-r--r--apps/files/src/views/favorites.spec.ts69
-rw-r--r--apps/files/src/views/favorites.ts2
13 files changed, 174 insertions, 172 deletions
diff --git a/apps/files/src/actions/deleteAction.spec.ts b/apps/files/src/actions/deleteAction.spec.ts
index 7b6bbfc9bf7..224b196d364 100644
--- a/apps/files/src/actions/deleteAction.spec.ts
+++ b/apps/files/src/actions/deleteAction.spec.ts
@@ -2,15 +2,20 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { action } from './deleteAction'
-import { expect } from '@jest/globals'
import { File, Folder, Permission, View, FileAction } from '@nextcloud/files'
+import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
+
import axios from '@nextcloud/axios'
import * as capabilities from '@nextcloud/capabilities'
-import eventBus from '@nextcloud/event-bus'
+import * as eventBus from '@nextcloud/event-bus'
+import { action } from './deleteAction'
import logger from '../logger'
+vi.mock('@nextcloud/auth')
+vi.mock('@nextcloud/axios')
+vi.mock('@nextcloud/capabilities')
+
const view = {
id: 'files',
name: 'Files',
@@ -22,8 +27,8 @@ const trashbinView = {
} as View
describe('Delete action conditions tests', () => {
- afterEach(() => {
- jest.restoreAllMocks()
+ beforeEach(() => {
+ vi.restoreAllMocks()
})
const file = new File({
@@ -82,7 +87,7 @@ describe('Delete action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('delete')
expect(action.displayName([file], view)).toBe('Delete file')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(100)
})
@@ -96,7 +101,7 @@ describe('Delete action conditions tests', () => {
})
test('Trashbin disabled displayName', () => {
- jest.spyOn(capabilities, 'getCapabilities').mockImplementation(() => {
+ vi.spyOn(capabilities, 'getCapabilities').mockImplementation(() => {
return {
files: {},
}
@@ -176,11 +181,11 @@ describe('Delete action enabled tests', () => {
describe('Delete action execute tests', () => {
afterEach(() => {
- jest.restoreAllMocks()
+ vi.restoreAllMocks()
})
test('Delete action', async () => {
- jest.spyOn(axios, 'delete')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'delete')
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
@@ -201,10 +206,10 @@ describe('Delete action execute tests', () => {
})
test('Delete action batch', async () => {
- jest.spyOn(axios, 'delete')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'delete')
+ vi.spyOn(eventBus, 'emit')
- const confirmMock = jest.fn()
+ const confirmMock = vi.fn()
// @ts-expect-error We only mock what needed
window.OC = { dialogs: { confirmDestructive: confirmMock } }
@@ -240,11 +245,11 @@ describe('Delete action execute tests', () => {
})
test('Delete action batch large set', async () => {
- jest.spyOn(axios, 'delete')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'delete')
+ vi.spyOn(eventBus, 'emit')
// Emulate the confirmation dialog to always confirm
- const confirmMock = jest.fn().mockImplementation((a, b, c, resolve) => resolve(true))
+ const confirmMock = vi.fn().mockImplementation((a, b, c, resolve) => resolve(true))
// @ts-expect-error We only mock what needed
window.OC = { dialogs: { confirmDestructive: confirmMock } }
@@ -310,16 +315,16 @@ describe('Delete action execute tests', () => {
})
test('Delete action batch trashbin disabled', async () => {
- jest.spyOn(axios, 'delete')
- jest.spyOn(eventBus, 'emit')
- jest.spyOn(capabilities, 'getCapabilities').mockImplementation(() => {
+ vi.spyOn(axios, 'delete')
+ vi.spyOn(eventBus, 'emit')
+ vi.spyOn(capabilities, 'getCapabilities').mockImplementation(() => {
return {
files: {},
}
})
// Emulate the confirmation dialog to always confirm
- const confirmMock = jest.fn().mockImplementation((a, b, c, resolve) => resolve(true))
+ const confirmMock = vi.fn().mockImplementation((a, b, c, resolve) => resolve(true))
// @ts-expect-error We only mock what needed
window.OC = { dialogs: { confirmDestructive: confirmMock } }
@@ -355,9 +360,9 @@ describe('Delete action execute tests', () => {
})
test('Delete fails', async () => {
- jest.spyOn(axios, 'delete').mockImplementation(() => { throw new Error('Mock error') })
- jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'delete').mockImplementation(() => { throw new Error('Mock error') })
+ vi.spyOn(logger, 'error').mockImplementation(() => vi.fn())
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
@@ -378,16 +383,16 @@ describe('Delete action execute tests', () => {
})
test('Delete is cancelled', async () => {
- jest.spyOn(axios, 'delete')
- jest.spyOn(eventBus, 'emit')
- jest.spyOn(capabilities, 'getCapabilities').mockImplementation(() => {
+ vi.spyOn(axios, 'delete')
+ vi.spyOn(eventBus, 'emit')
+ vi.spyOn(capabilities, 'getCapabilities').mockImplementation(() => {
return {
files: {},
}
})
// Emulate the confirmation dialog to always confirm
- const confirmMock = jest.fn().mockImplementation((a, b, c, resolve) => resolve(false))
+ const confirmMock = vi.fn().mockImplementation((a, b, c, resolve) => resolve(false))
// @ts-expect-error We only mock what needed
window.OC = { dialogs: { confirmDestructive: confirmMock } }
diff --git a/apps/files/src/actions/downloadAction.spec.ts b/apps/files/src/actions/downloadAction.spec.ts
index 59e533441be..2c24625e90e 100644
--- a/apps/files/src/actions/downloadAction.spec.ts
+++ b/apps/files/src/actions/downloadAction.spec.ts
@@ -2,9 +2,10 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { action } from './downloadAction'
-import { expect } from '@jest/globals'
import { File, Folder, Permission, View, FileAction, DefaultType } from '@nextcloud/files'
+import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'
+
+import { action } from './downloadAction'
const view = {
id: 'files',
@@ -22,7 +23,7 @@ describe('Download action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('download')
expect(action.displayName([], view)).toBe('Download')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBe(DefaultType.DEFAULT)
expect(action.order).toBe(30)
})
@@ -83,11 +84,12 @@ describe('Download action enabled tests', () => {
describe('Download action execute tests', () => {
const link = {
- click: jest.fn(),
+ click: vi.fn(),
} as unknown as HTMLAnchorElement
beforeEach(() => {
- jest.spyOn(document, 'createElement').mockImplementation(() => link)
+ vi.resetAllMocks()
+ vi.spyOn(document, 'createElement').mockImplementation(() => link)
})
test('Download single file', async () => {
diff --git a/apps/files/src/actions/editLocallyAction.spec.ts b/apps/files/src/actions/editLocallyAction.spec.ts
index ca2e1d05f96..4d07bb15189 100644
--- a/apps/files/src/actions/editLocallyAction.spec.ts
+++ b/apps/files/src/actions/editLocallyAction.spec.ts
@@ -2,25 +2,15 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { action } from './editLocallyAction'
-import { expect } from '@jest/globals'
import { File, Permission, View, FileAction } from '@nextcloud/files'
-import { DialogBuilder, showError } from '@nextcloud/dialogs'
-import axios from '@nextcloud/axios'
+import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'
-const dialogBuilder = {
- setName: jest.fn().mockReturnThis(),
- setText: jest.fn().mockReturnThis(),
- setButtons: jest.fn().mockReturnThis(),
- build: jest.fn().mockReturnValue({
- show: jest.fn().mockResolvedValue(true),
- }),
-} as unknown as DialogBuilder
+import axios from '@nextcloud/axios'
+import * as nextcloudDialogs from '@nextcloud/dialogs'
+import { action } from './editLocallyAction'
-jest.mock('@nextcloud/dialogs', () => ({
- DialogBuilder: jest.fn(() => dialogBuilder),
- showError: jest.fn(),
-}))
+vi.mock('@nextcloud/auth')
+vi.mock('@nextcloud/axios')
const view = {
id: 'files',
@@ -31,7 +21,7 @@ const view = {
beforeAll(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any)._oc_webroot = '';
- (window as any).OCA = { Viewer: { open: jest.fn() } }
+ (window as any).OCA = { Viewer: { open: vi.fn() } }
})
describe('Edit locally action conditions tests', () => {
@@ -39,7 +29,7 @@ describe('Edit locally action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('edit-locally')
expect(action.displayName([], view)).toBe('Edit locally')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(25)
})
@@ -118,16 +108,22 @@ describe('Edit locally action enabled tests', () => {
})
describe('Edit locally action execute tests', () => {
+ let spyShowDialog
+ beforeEach(() => {
+ vi.resetAllMocks()
+ spyShowDialog = vi.spyOn(nextcloudDialogs.Dialog.prototype, 'show')
+ .mockImplementation(() => Promise.resolve())
+ })
+
test('Edit locally opens proper URL', async () => {
- jest.spyOn(axios, 'post').mockImplementation(async () => ({
- data: { ocs: { data: { token: 'foobar' } } }
+ vi.spyOn(axios, 'post').mockImplementation(async () => ({
+ data: { ocs: { data: { token: 'foobar' } } },
}))
- const mockedShowError = jest.mocked(showError)
- const spyDialogBuilder = jest.spyOn(dialogBuilder, 'build')
+ const showError = vi.spyOn(nextcloudDialogs, 'showError')
const file = new File({
id: 1,
- source: 'http://localhost/remote.php/dav/files/admin/foobar.txt',
+ source: 'http://nextcloud.local/remote.php/dav/files/admin/foobar.txt',
owner: 'admin',
mime: 'text/plain',
permissions: Permission.UPDATE,
@@ -135,24 +131,23 @@ describe('Edit locally action execute tests', () => {
const exec = await action.exec(file, view, '/')
- expect(spyDialogBuilder).toBeCalled()
+ expect(spyShowDialog).toBeCalled()
// Silent action
expect(exec).toBe(null)
expect(axios.post).toBeCalledTimes(1)
- expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files/api/v1/openlocaleditor?format=json', { path: '/foobar.txt' })
- expect(mockedShowError).toBeCalledTimes(0)
- expect(window.location.href).toBe('nc://open/test@localhost/foobar.txt?token=foobar')
+ expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files/api/v1/openlocaleditor?format=json', { path: '/foobar.txt' })
+ expect(showError).toBeCalledTimes(0)
+ expect(window.location.href).toBe('nc://open/test@nextcloud.local/foobar.txt?token=foobar')
})
test('Edit locally fails and shows error', async () => {
- jest.spyOn(axios, 'post').mockImplementation(async () => ({}))
- const mockedShowError = jest.mocked(showError)
- const spyDialogBuilder = jest.spyOn(dialogBuilder, 'build')
+ vi.spyOn(axios, 'post').mockImplementation(async () => ({}))
+ const showError = vi.spyOn(nextcloudDialogs, 'showError')
const file = new File({
id: 1,
- source: 'http://localhost/remote.php/dav/files/admin/foobar.txt',
+ source: 'http://nextcloud.local/remote.php/dav/files/admin/foobar.txt',
owner: 'admin',
mime: 'text/plain',
permissions: Permission.UPDATE,
@@ -160,14 +155,14 @@ describe('Edit locally action execute tests', () => {
const exec = await action.exec(file, view, '/')
- expect(spyDialogBuilder).toBeCalled()
+ expect(spyShowDialog).toBeCalled()
// Silent action
expect(exec).toBe(null)
expect(axios.post).toBeCalledTimes(1)
- expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files/api/v1/openlocaleditor?format=json', { path: '/foobar.txt' })
- expect(mockedShowError).toBeCalledTimes(1)
- expect(mockedShowError).toBeCalledWith('Failed to redirect to client')
- expect(window.location.href).toBe('http://localhost/')
+ expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files/api/v1/openlocaleditor?format=json', { path: '/foobar.txt' })
+ expect(showError).toBeCalledTimes(1)
+ expect(showError).toBeCalledWith('Failed to redirect to client')
+ expect(window.location.href).toBe('http://nextcloud.local/')
})
})
diff --git a/apps/files/src/actions/favoriteAction.spec.ts b/apps/files/src/actions/favoriteAction.spec.ts
index cbf0038961a..96768c4887a 100644
--- a/apps/files/src/actions/favoriteAction.spec.ts
+++ b/apps/files/src/actions/favoriteAction.spec.ts
@@ -2,14 +2,18 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { action } from './favoriteAction'
-import { expect } from '@jest/globals'
import { File, Permission, View, FileAction } from '@nextcloud/files'
+import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'
+
+import { action } from './favoriteAction'
import axios from '@nextcloud/axios'
-import eventBus from '@nextcloud/event-bus'
+import * as eventBus from '@nextcloud/event-bus'
import * as favoriteAction from './favoriteAction'
import logger from '../logger'
+vi.mock('@nextcloud/auth')
+vi.mock('@nextcloud/axios')
+
const view = {
id: 'files',
name: 'Files',
@@ -20,13 +24,12 @@ const favoriteView = {
name: 'Favorites',
} as View
-window.OC = {
- ...window.OC,
- TAG_FAVORITE: '_$!<Favorite>!$_',
-}
-
// Mock webroot variable
beforeAll(() => {
+ window.OC = {
+ ...window.OC,
+ TAG_FAVORITE: '_$!<Favorite>!$_',
+ };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any)._oc_webroot = ''
})
@@ -43,7 +46,7 @@ describe('Favorite action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('favorite')
expect(action.displayName([file], view)).toBe('Add to favorites')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(-50)
})
@@ -129,13 +132,11 @@ describe('Favorite action enabled tests', () => {
})
describe('Favorite action execute tests', () => {
- afterEach(() => {
- jest.spyOn(axios, 'post').mockRestore()
- })
+ beforeEach(() => { vi.resetAllMocks() })
test('Favorite triggers tag addition', async () => {
- jest.spyOn(axios, 'post')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'post')
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
@@ -159,8 +160,8 @@ describe('Favorite action execute tests', () => {
})
test('Favorite triggers tag removal', async () => {
- jest.spyOn(axios, 'post')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'post')
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
@@ -187,8 +188,8 @@ describe('Favorite action execute tests', () => {
})
test('Favorite triggers node removal if favorite view and root dir', async () => {
- jest.spyOn(axios, 'post')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'post')
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
@@ -216,8 +217,8 @@ describe('Favorite action execute tests', () => {
})
test('Favorite does NOT triggers node removal if favorite view but NOT root dir', async () => {
- jest.spyOn(axios, 'post')
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(axios, 'post')
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
@@ -246,8 +247,8 @@ describe('Favorite action execute tests', () => {
test('Favorite fails and show error', async () => {
const error = new Error('Mock error')
- jest.spyOn(axios, 'post').mockImplementation(() => { throw new Error('Mock error') })
- jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
+ vi.spyOn(axios, 'post').mockImplementation(() => { throw new Error('Mock error') })
+ vi.spyOn(logger, 'error').mockImplementation(() => vi.fn())
const file = new File({
id: 1,
@@ -276,8 +277,8 @@ describe('Favorite action execute tests', () => {
test('Removing from favorites fails and show error', async () => {
const error = new Error('Mock error')
- jest.spyOn(axios, 'post').mockImplementation(() => { throw error })
- jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
+ vi.spyOn(axios, 'post').mockImplementation(() => { throw error })
+ vi.spyOn(logger, 'error').mockImplementation(() => vi.fn())
const file = new File({
id: 1,
@@ -306,9 +307,11 @@ describe('Favorite action execute tests', () => {
})
describe('Favorite action batch execute tests', () => {
+ beforeEach(() => { vi.restoreAllMocks() })
+
test('Favorite action batch execute with mixed files', async () => {
- jest.spyOn(favoriteAction, 'favoriteNode')
- jest.spyOn(axios, 'post')
+ vi.spyOn(favoriteAction, 'favoriteNode')
+ vi.spyOn(axios, 'post')
const file1 = new File({
id: 1,
@@ -336,15 +339,14 @@ describe('Favorite action batch execute tests', () => {
expect(exec).toStrictEqual([true, true])
expect([file1, file2].every(file => file.attributes.favorite === 1)).toBe(true)
- expect(favoriteAction.favoriteNode).toBeCalledTimes(2)
expect(axios.post).toBeCalledTimes(2)
expect(axios.post).toHaveBeenNthCalledWith(1, '/index.php/apps/files/api/v1/files/foo.txt', { tags: ['_$!<Favorite>!$_'] })
expect(axios.post).toHaveBeenNthCalledWith(2, '/index.php/apps/files/api/v1/files/bar.txt', { tags: ['_$!<Favorite>!$_'] })
})
test('Remove from favorite action batch execute with favorites only files', async () => {
- jest.spyOn(favoriteAction, 'favoriteNode')
- jest.spyOn(axios, 'post')
+ vi.spyOn(favoriteAction, 'favoriteNode')
+ vi.spyOn(axios, 'post')
const file1 = new File({
id: 1,
@@ -372,7 +374,6 @@ describe('Favorite action batch execute tests', () => {
expect(exec).toStrictEqual([true, true])
expect([file1, file2].every(file => file.attributes.favorite === 0)).toBe(true)
- expect(favoriteAction.favoriteNode).toBeCalledTimes(2)
expect(axios.post).toBeCalledTimes(2)
expect(axios.post).toHaveBeenNthCalledWith(1, '/index.php/apps/files/api/v1/files/foo.txt', { tags: [] })
expect(axios.post).toHaveBeenNthCalledWith(2, '/index.php/apps/files/api/v1/files/bar.txt', { tags: [] })
diff --git a/apps/files/src/actions/openFolderAction.spec.ts b/apps/files/src/actions/openFolderAction.spec.ts
index cbbbe38f15e..066ad5d86d8 100644
--- a/apps/files/src/actions/openFolderAction.spec.ts
+++ b/apps/files/src/actions/openFolderAction.spec.ts
@@ -2,8 +2,8 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { expect } from '@jest/globals'
import { File, Folder, Node, Permission, View, DefaultType, FileAction } from '@nextcloud/files'
+import { describe, expect, test, vi } from 'vitest'
import { action } from './openFolderAction'
@@ -24,7 +24,7 @@ describe('Open folder action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('open-folder')
expect(action.displayName([folder], view)).toBe('Open folder FooBar')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBe(DefaultType.HIDDEN)
expect(action.order).toBe(-100)
})
@@ -100,7 +100,7 @@ describe('Open folder action enabled tests', () => {
describe('Open folder action execute tests', () => {
test('Open folder', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -119,7 +119,7 @@ describe('Open folder action execute tests', () => {
})
test('Open folder fails without node', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -129,7 +129,7 @@ describe('Open folder action execute tests', () => {
})
test('Open folder fails without Folder', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
diff --git a/apps/files/src/actions/openInFilesAction.spec.ts b/apps/files/src/actions/openInFilesAction.spec.ts
index 88a9716914b..e732270d4c0 100644
--- a/apps/files/src/actions/openInFilesAction.spec.ts
+++ b/apps/files/src/actions/openInFilesAction.spec.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { action } from './openInFilesAction'
-import { expect } from '@jest/globals'
+import { describe, expect, test, vi } from 'vitest'
import { File, Folder, Permission, View, DefaultType, FileAction } from '@nextcloud/files'
const view = {
@@ -42,7 +42,7 @@ describe('Open in files action enabled tests', () => {
describe('Open in files action execute tests', () => {
test('Open in files', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -64,7 +64,7 @@ describe('Open in files action execute tests', () => {
})
test('Open in files with folder', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
diff --git a/apps/files/src/actions/renameAction.spec.ts b/apps/files/src/actions/renameAction.spec.ts
index f0428996972..b309c11d9a6 100644
--- a/apps/files/src/actions/renameAction.spec.ts
+++ b/apps/files/src/actions/renameAction.spec.ts
@@ -3,9 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { action } from './renameAction'
-import { expect } from '@jest/globals'
import { File, Permission, View, FileAction } from '@nextcloud/files'
-import eventBus from '@nextcloud/event-bus'
+import * as eventBus from '@nextcloud/event-bus'
+import { describe, expect, test, vi } from 'vitest'
const view = {
id: 'files',
@@ -17,7 +17,7 @@ describe('Rename action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('rename')
expect(action.displayName([], view)).toBe('Rename')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(10)
})
@@ -73,7 +73,7 @@ describe('Rename action enabled tests', () => {
describe('Rename action exec tests', () => {
test('Rename', async () => {
- jest.spyOn(eventBus, 'emit')
+ vi.spyOn(eventBus, 'emit')
const file = new File({
id: 1,
diff --git a/apps/files/src/actions/sidebarAction.spec.ts b/apps/files/src/actions/sidebarAction.spec.ts
index 21b48eba105..9755f519306 100644
--- a/apps/files/src/actions/sidebarAction.spec.ts
+++ b/apps/files/src/actions/sidebarAction.spec.ts
@@ -2,8 +2,8 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { expect } from '@jest/globals'
import { File, Permission, View, FileAction } from '@nextcloud/files'
+import { describe, expect, test, vi } from 'vitest'
import { action } from './sidebarAction'
import logger from '../logger'
@@ -18,7 +18,7 @@ describe('Open sidebar action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('details')
expect(action.displayName([], view)).toBe('Open details')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(-50)
})
@@ -107,9 +107,9 @@ describe('Open sidebar action enabled tests', () => {
describe('Open sidebar action exec tests', () => {
test('Open sidebar', async () => {
- const openMock = jest.fn()
+ const openMock = vi.fn()
window.OCA = { Files: { Sidebar: { open: openMock } } }
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -133,9 +133,9 @@ describe('Open sidebar action exec tests', () => {
})
test('Open sidebar fails', async () => {
- const openMock = jest.fn(() => { throw new Error('Mock error') })
+ const openMock = vi.fn(() => { throw new Error('Mock error') })
window.OCA = { Files: { Sidebar: { open: openMock } } }
- jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
+ vi.spyOn(logger, 'error').mockImplementation(() => vi.fn())
const file = new File({
id: 1,
diff --git a/apps/files/src/actions/viewInFolderAction.spec.ts b/apps/files/src/actions/viewInFolderAction.spec.ts
index c75151a4c38..8aa8bc81922 100644
--- a/apps/files/src/actions/viewInFolderAction.spec.ts
+++ b/apps/files/src/actions/viewInFolderAction.spec.ts
@@ -2,9 +2,9 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { action } from './viewInFolderAction'
-import { expect } from '@jest/globals'
import { File, Folder, Node, Permission, View, FileAction } from '@nextcloud/files'
+import { describe, expect, test, vi } from 'vitest'
+import { action } from './viewInFolderAction'
const view = {
id: 'trashbin',
@@ -21,7 +21,7 @@ describe('View in folder action conditions tests', () => {
expect(action).toBeInstanceOf(FileAction)
expect(action.id).toBe('view-in-folder')
expect(action.displayName([], view)).toBe('View in folder')
- expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
+ expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(80)
expect(action.enabled).toBeDefined()
@@ -113,7 +113,7 @@ describe('View in folder action enabled tests', () => {
describe('View in folder action execute tests', () => {
test('View in folder', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -133,7 +133,7 @@ describe('View in folder action execute tests', () => {
})
test('View in (sub) folder', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -154,7 +154,7 @@ describe('View in folder action execute tests', () => {
})
test('View in folder fails without node', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
@@ -164,7 +164,7 @@ describe('View in folder action execute tests', () => {
})
test('View in folder fails without File', async () => {
- const goToRouteMock = jest.fn()
+ const goToRouteMock = vi.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }
diff --git a/apps/files/src/composables/useNavigation.spec.ts b/apps/files/src/composables/useNavigation.spec.ts
index 364c9ab653d..efea7103126 100644
--- a/apps/files/src/composables/useNavigation.spec.ts
+++ b/apps/files/src/composables/useNavigation.spec.ts
@@ -2,11 +2,14 @@
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { beforeEach, describe, expect, it, jest } from '@jest/globals'
-import nextcloudFiles, { Navigation, View } from '@nextcloud/files'
+import { beforeEach, describe, expect, it, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { defineComponent } from 'vue'
+
import { useNavigation } from './useNavigation'
+import * as nextcloudFiles from '@nextcloud/files'
+
+const { Navigation, View } = nextcloudFiles
// Just a wrapper so we can test the composable
const TestComponent = defineComponent({
@@ -21,7 +24,7 @@ const TestComponent = defineComponent({
})
describe('Composables: useNavigation', () => {
- const spy = jest.spyOn(nextcloudFiles, 'getNavigation')
+ const spy = vi.spyOn(nextcloudFiles, 'getNavigation')
let navigation: Navigation
describe('currentView', () => {
diff --git a/apps/files/src/services/DropServiceUtils.spec.ts b/apps/files/src/services/DropServiceUtils.spec.ts
index 9f947531198..5f4370c7894 100644
--- a/apps/files/src/services/DropServiceUtils.spec.ts
+++ b/apps/files/src/services/DropServiceUtils.spec.ts
@@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { describe, it, expect } from '@jest/globals'
+import { beforeAll, describe, expect, it, vi } from 'vitest'
import { FileSystemDirectoryEntry, FileSystemFileEntry, fileSystemEntryToDataTransferItem, DataTransferItem as DataTransferItemMock } from '../../../../__tests__/FileSystemAPIUtils'
import { join } from 'node:path'
@@ -88,20 +88,17 @@ describe('Filesystem API traverseTree', () => {
describe('DropService dataTransferToFileTree', () => {
beforeAll(() => {
+ // @ts-expect-error jsdom doesn't have DataTransferItem
+ delete window.DataTransferItem
// DataTransferItem doesn't exists in jsdom, let's mock
// a dumb one so we can check the instanceof
// @ts-expect-error jsdom doesn't have DataTransferItem
window.DataTransferItem = DataTransferItemMock
})
- afterAll(() => {
- // @ts-expect-error jsdom doesn't have DataTransferItem
- delete window.DataTransferItem
- })
-
it('Should return a RootDirectory with Filesystem API', async () => {
- jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
- jest.spyOn(logger, 'warn').mockImplementation(() => jest.fn())
+ vi.spyOn(logger, 'error').mockImplementation(() => vi.fn())
+ vi.spyOn(logger, 'warn').mockImplementation(() => vi.fn())
const dataTransferItems = buildDataTransferItemArray('root', dataTree)
const fileTree = await dataTransferToFileTree(dataTransferItems as unknown as DataTransferItem[])
@@ -121,8 +118,8 @@ describe('DropService dataTransferToFileTree', () => {
})
it('Should return a RootDirectory with legacy File API ignoring recursive directories', async () => {
- jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
- jest.spyOn(logger, 'warn').mockImplementation(() => jest.fn())
+ vi.spyOn(logger, 'error').mockImplementation(() => vi.fn())
+ vi.spyOn(logger, 'warn').mockImplementation(() => vi.fn())
const dataTransferItems = buildDataTransferItemArray('root', dataTree, false)
diff --git a/apps/files/src/views/favorites.spec.ts b/apps/files/src/views/favorites.spec.ts
index 976334d6bde..b2aa292f936 100644
--- a/apps/files/src/views/favorites.spec.ts
+++ b/apps/files/src/views/favorites.spec.ts
@@ -3,20 +3,18 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import { basename } from 'path'
-import { expect } from '@jest/globals'
import { Folder, Navigation, getNavigation } from '@nextcloud/files'
import { CancelablePromise } from 'cancelable-promise'
-import eventBus, { emit } from '@nextcloud/event-bus'
+import { basename } from 'path'
+import { beforeEach, describe, expect, test, vi } from 'vitest'
+import * as eventBus from '@nextcloud/event-bus'
import * as initialState from '@nextcloud/initial-state'
import { action } from '../actions/favoriteAction'
import * as favoritesService from '../services/Favorites'
import registerFavoritesView from './favorites'
-jest.mock('webdav/dist/node/request.js', () => ({
- request: jest.fn(),
-}))
+vi.mock('@nextcloud/axios')
window.OC = {
...window.OC,
@@ -32,17 +30,16 @@ declare global {
describe('Favorites view definition', () => {
let Navigation
beforeEach(() => {
- Navigation = getNavigation()
- expect(window._nc_navigation).toBeDefined()
- })
+ vi.resetAllMocks()
- afterEach(() => {
delete window._nc_navigation
+ Navigation = getNavigation()
+ expect(window._nc_navigation).toBeDefined()
})
test('Default empty favorite view', () => {
- jest.spyOn(eventBus, 'subscribe')
- jest.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
+ vi.spyOn(eventBus, 'subscribe')
+ vi.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
registerFavoritesView()
const favoritesView = Navigation.views.find(view => view.id === 'favorites')
@@ -61,7 +58,7 @@ describe('Favorites view definition', () => {
expect(favoritesView?.id).toBe('favorites')
expect(favoritesView?.name).toBe('Favorites')
expect(favoritesView?.caption).toBeDefined()
- expect(favoritesView?.icon).toBe('<svg>SvgMock</svg>')
+ expect(favoritesView?.icon).toMatch(/<svg.+<\/svg>/)
expect(favoritesView?.order).toBe(15)
expect(favoritesView?.columns).toStrictEqual([])
expect(favoritesView?.getContents).toBeDefined()
@@ -73,8 +70,8 @@ describe('Favorites view definition', () => {
{ fileid: 2, path: '/bar' },
{ fileid: 3, path: '/foo/bar' },
]
- jest.spyOn(initialState, 'loadState').mockReturnValue(favoriteFolders)
- jest.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
+ vi.spyOn(initialState, 'loadState').mockReturnValue(favoriteFolders)
+ vi.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
registerFavoritesView()
const favoritesView = Navigation.views.find(view => view.id === 'favorites')
@@ -90,7 +87,7 @@ describe('Favorites view definition', () => {
expect(favoriteView).toBeDefined()
expect(favoriteView?.id).toBeDefined()
expect(favoriteView?.name).toBe(basename(folder.path))
- expect(favoriteView?.icon).toBe('<svg>SvgMock</svg>')
+ expect(favoriteView?.icon).toMatch(/<svg.+<\/svg>/)
expect(favoriteView?.order).toBe(index)
expect(favoriteView?.params).toStrictEqual({
dir: folder.path,
@@ -104,20 +101,19 @@ describe('Favorites view definition', () => {
})
})
-describe('Dynamic update of favourite folders', () => {
+describe('Dynamic update of favorite folders', () => {
let Navigation
beforeEach(() => {
- Navigation = getNavigation()
- })
+ vi.restoreAllMocks()
- afterEach(() => {
delete window._nc_navigation
+ Navigation = getNavigation()
})
test('Add a favorite folder creates a new entry in the navigation', async () => {
- jest.spyOn(eventBus, 'emit')
- jest.spyOn(initialState, 'loadState').mockReturnValue([])
- jest.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
+ vi.spyOn(eventBus, 'emit')
+ vi.spyOn(initialState, 'loadState').mockReturnValue([])
+ vi.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
registerFavoritesView()
const favoritesView = Navigation.views.find(view => view.id === 'favorites')
@@ -131,7 +127,7 @@ describe('Dynamic update of favourite folders', () => {
// Create new folder to favorite
const folder = new Folder({
id: 1,
- source: 'http://localhost/remote.php/dav/files/admin/Foo/Bar',
+ source: 'http://nextcloud.local/remote.php/dav/files/admin/Foo/Bar',
owner: 'admin',
})
@@ -143,10 +139,9 @@ describe('Dynamic update of favourite folders', () => {
})
test('Remove a favorite folder remove the entry from the navigation column', async () => {
- jest.spyOn(eventBus, 'emit')
- jest.spyOn(eventBus, 'subscribe')
- jest.spyOn(initialState, 'loadState').mockReturnValue([{ fileid: 42, path: '/Foo/Bar' }])
- jest.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
+ vi.spyOn(eventBus, 'emit')
+ vi.spyOn(initialState, 'loadState').mockReturnValue([{ fileid: 42, path: '/Foo/Bar' }])
+ vi.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
registerFavoritesView()
let favoritesView = Navigation.views.find(view => view.id === 'favorites')
@@ -160,7 +155,7 @@ describe('Dynamic update of favourite folders', () => {
// Create new folder to favorite
const folder = new Folder({
id: 1,
- source: 'http://localhost/remote.php/dav/files/admin/Foo/Bar',
+ source: 'http://nextcloud.local/remote.php/dav/files/admin/Foo/Bar',
owner: 'admin',
root: '/files/admin',
attributes: {
@@ -168,11 +163,15 @@ describe('Dynamic update of favourite folders', () => {
},
})
+ const fo = vi.fn()
+ eventBus.subscribe('files:favorites:removed', fo)
+
// Exec the action
await action.exec(folder, favoritesView, '/')
expect(eventBus.emit).toHaveBeenCalledTimes(1)
expect(eventBus.emit).toHaveBeenCalledWith('files:favorites:removed', folder)
+ expect(fo).toHaveBeenCalled()
favoritesView = Navigation.views.find(view => view.id === 'favorites')
favoriteFoldersViews = Navigation.views.filter(view => view.parent === 'favorites')
@@ -184,9 +183,9 @@ describe('Dynamic update of favourite folders', () => {
})
test('Renaming a favorite folder updates the navigation', async () => {
- jest.spyOn(eventBus, 'emit')
- jest.spyOn(initialState, 'loadState').mockReturnValue([])
- jest.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
+ vi.spyOn(eventBus, 'emit')
+ vi.spyOn(initialState, 'loadState').mockReturnValue([])
+ vi.spyOn(favoritesService, 'getContents').mockReturnValue(CancelablePromise.resolve({ folder: {} as Folder, contents: [] }))
registerFavoritesView()
const favoritesView = Navigation.views.find(view => view.id === 'favorites')
@@ -202,7 +201,7 @@ describe('Dynamic update of favourite folders', () => {
// Create new folder to favorite
const folder = new Folder({
id: 1,
- source: 'http://localhost/remote.php/dav/files/admin/Foo/Bar',
+ source: 'http://nextcloud.local/remote.php/dav/files/admin/Foo/Bar',
owner: 'admin',
})
@@ -213,12 +212,12 @@ describe('Dynamic update of favourite folders', () => {
// Create a folder with the same id but renamed
const renamedFolder = new Folder({
id: 1,
- source: 'http://localhost/remote.php/dav/files/admin/Foo/Bar.renamed',
+ source: 'http://nextcloud.local/remote.php/dav/files/admin/Foo/Bar.renamed',
owner: 'admin',
})
// Exec the rename action
- emit('files:node:renamed', renamedFolder)
+ eventBus.emit('files:node:renamed', renamedFolder)
expect(eventBus.emit).toHaveBeenNthCalledWith(2, 'files:node:renamed', renamedFolder)
})
})
diff --git a/apps/files/src/views/favorites.ts b/apps/files/src/views/favorites.ts
index e09587a0d5d..3af8c49498f 100644
--- a/apps/files/src/views/favorites.ts
+++ b/apps/files/src/views/favorites.ts
@@ -90,7 +90,7 @@ export default () => {
})
/**
- * Remove favourites navigation when a folder is removed
+ * Remove favorites navigation when a folder is removed
*/
subscribe('files:favorites:removed', (node: Node) => {
if (node.type !== FileType.Folder) {