diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-08-24 16:53:33 +0200 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-08-26 17:27:22 +0200 |
commit | a5e58dc45e2078fa6e2330e78d17a73f92168974 (patch) | |
tree | 508f45285616e97677b5493f10a4e0513d478924 | |
parent | c0b39bb9095b9e0421314c99d3ff0e149a21c435 (diff) | |
download | nextcloud-server-a5e58dc45e2078fa6e2330e78d17a73f92168974.tar.gz nextcloud-server-a5e58dc45e2078fa6e2330e78d17a73f92168974.zip |
test: Migrated all Jest tests to vitest
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
33 files changed, 776 insertions, 336 deletions
diff --git a/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts b/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts index dc8892769e3..e8020f1f029 100644 --- a/apps/comments/src/actions/inlineUnreadCommentsAction.spec.ts +++ b/apps/comments/src/actions/inlineUnreadCommentsAction.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 './inlineUnreadCommentsAction' -import { expect } from '@jest/globals' import { File, Permission, View, FileAction } from '@nextcloud/files' +import { describe, expect, test, vi } from 'vitest' + +import { action } from './inlineUnreadCommentsAction' import logger from '../logger' const view = { @@ -29,7 +30,7 @@ describe('Inline unread comments action display name tests', () => { expect(action.id).toBe('comments-unread') expect(action.displayName([file], view)).toBe('') expect(action.title!([file], view)).toBe('1 new comment') - expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>') + expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/) expect(action.enabled!([file], view)).toBe(true) expect(action.inline!(file, view)).toBe(true) expect(action.default).toBeUndefined() @@ -115,8 +116,8 @@ describe('Inline unread comments action enabled tests', () => { describe('Inline unread comments action execute tests', () => { test('Action opens sidebar', async () => { - const openMock = jest.fn() - const setActiveTabMock = jest.fn() + const openMock = vi.fn() + const setActiveTabMock = vi.fn() window.OCA = { Files: { Sidebar: { @@ -145,8 +146,8 @@ describe('Inline unread comments action execute tests', () => { }) test('Action handles sidebar open failure', async () => { - const openMock = jest.fn(() => { throw new Error('Mock error') }) - const setActiveTabMock = jest.fn() + const openMock = vi.fn(() => { throw new Error('Mock error') }) + const setActiveTabMock = vi.fn() window.OCA = { Files: { Sidebar: { @@ -155,7 +156,7 @@ describe('Inline unread comments action execute tests', () => { }, }, } - jest.spyOn(logger, 'error').mockImplementation(() => jest.fn()) + vi.spyOn(logger, 'error').mockImplementation(() => vi.fn()) const file = new File({ id: 1, diff --git a/apps/dav/src/views/CalDavSettings.spec.js b/apps/dav/src/views/CalDavSettings.spec.js index feaca3a735f..7a4345b3ddf 100644 --- a/apps/dav/src/views/CalDavSettings.spec.js +++ b/apps/dav/src/views/CalDavSettings.spec.js @@ -3,40 +3,33 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import { render } from '@testing-library/vue' +import { beforeEach, describe, expect, test, vi } from 'vitest' + import CalDavSettings from './CalDavSettings.vue' -// eslint-disable-next-line no-unused-vars -import { generateUrl } from '@nextcloud/router' -jest.mock('@nextcloud/axios') -jest.mock('@nextcloud/router', () => { +vi.mock('@nextcloud/axios') +vi.mock('@nextcloud/router', () => { return { generateUrl(url) { return url }, } }) -jest.mock('@nextcloud/initial-state', () => { +vi.mock('@nextcloud/initial-state', () => { return { - loadState: jest.fn(() => 'https://docs.nextcloud.com/server/23/go.php?to=user-sync-calendars'), + loadState: vi.fn(() => 'https://docs.nextcloud.com/server/23/go.php?to=user-sync-calendars'), } }) describe('CalDavSettings', () => { - const originalOC = global.OC - const originalOCP = global.OCP - beforeEach(() => { - global.OC = { requestToken: 'secret' } - global.OCP = { + window.OC = { requestToken: 'secret' } + window.OCP = { AppConfig: { - setValue: jest.fn(), + setValue: vi.fn(), }, } }) - afterAll(() => { - global.OC = originalOC - global.OCP = originalOCP - }) test('interactions', async () => { const TLUtils = render( @@ -53,7 +46,7 @@ describe('CalDavSettings', () => { }, }, Vue => { - Vue.prototype.$t = jest.fn((app, text) => text) + Vue.prototype.$t = vi.fn((app, text) => text) }, ) expect(TLUtils.container).toMatchSnapshot() diff --git a/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap b/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap index 9575e4ed79a..ea307542ee9 100644 --- a/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap +++ b/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap @@ -1,4 +1,437 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`CalDavSettings > interactions 1`] = ` +<div> + <div + class="settings-section settings-section--limit-width" + data-v-0974f50a="" + data-v-6b8d4c30="" + > + <h2 + class="settings-section__name" + data-v-0974f50a="" + > + Calendar server + <a + aria-label="External documentation for Calendar server" + class="settings-section__info" + data-v-0974f50a="" + href="https://docs.nextcloud.com/server/23/go.php?to=user-sync-calendars" + rel="noreferrer nofollow" + target="_blank" + title="External documentation for Calendar server" + > + <span + aria-hidden="true" + class="material-design-icon help-circle-icon" + data-v-0974f50a="" + role="img" + > + <svg + class="material-design-icon__svg" + fill="currentColor" + height="20" + viewBox="0 0 24 24" + width="20" + > + <path + d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" + > + <!----> + </path> + </svg> + </span> + </a> + </h2> + <!----> + <p + class="settings-hint" + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Also install the + <a + href="../apps/office/calendar" + target="_blank" + > + Calendar app + </a> + , or + <a + href="https://docs.nextcloud.com/server/23/go.php?to=user-sync-calendars" + rel="noreferrer noopener" + target="_blank" + > + connect your desktop & mobile for syncing ↗ + </a> + . + </p> + <p + data-v-0974f50a="" + data-v-6b8d4c30="" + > + <span + class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked" + data-v-0974f50a="" + data-v-6b8d4c30="" + data-v-feaabebe="" + style="--icon-size: 36px; --icon-height: 16px;" + > + <input + aria-labelledby="caldavSendInvitations-label" + class="checkbox-radio-switch__input" + data-v-feaabebe="" + id="caldavSendInvitations" + type="checkbox" + value="" + /> + <span + class="checkbox-content checkbox-radio-switch__content checkbox-content-switch checkbox-content--has-text" + data-v-e75842d8="" + data-v-feaabebe="" + id="caldavSendInvitations-label" + > + <span + aria-hidden="true" + class="checkbox-content__icon checkbox-content__icon--checked checkbox-radio-switch__icon" + data-v-e75842d8="" + inert="inert" + > + <span + aria-hidden="true" + class="material-design-icon toggle-switch-icon" + data-v-e75842d8="" + role="img" + > + <svg + class="material-design-icon__svg" + fill="currentColor" + height="36" + viewBox="0 0 24 24" + width="36" + > + <path + d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z" + > + <!----> + </path> + </svg> + </span> + </span> + <span + class="checkbox-content__text checkbox-radio-switch__text" + data-v-e75842d8="" + > + Send invitations to attendees + </span> + </span> + </span> + <em + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Please make sure to properly set up + <a + href="../admin#mail_general_settings" + > + the email server + </a> + . + </em> + </p> + <p + data-v-0974f50a="" + data-v-6b8d4c30="" + > + <span + class="checkbox-radio-switch checkbox checkbox-radio-switch-switch checkbox-radio-switch--checked" + data-v-0974f50a="" + data-v-6b8d4c30="" + data-v-feaabebe="" + style="--icon-size: 36px; --icon-height: 16px;" + > + <input + aria-labelledby="caldavGenerateBirthdayCalendar-label" + class="checkbox-radio-switch__input" + data-v-feaabebe="" + id="caldavGenerateBirthdayCalendar" + type="checkbox" + value="" + /> + <span + class="checkbox-content checkbox-radio-switch__content checkbox-content-switch checkbox-content--has-text" + data-v-e75842d8="" + data-v-feaabebe="" + id="caldavGenerateBirthdayCalendar-label" + > + <span + aria-hidden="true" + class="checkbox-content__icon checkbox-content__icon--checked checkbox-radio-switch__icon" + data-v-e75842d8="" + inert="inert" + > + <span + aria-hidden="true" + class="material-design-icon toggle-switch-icon" + data-v-e75842d8="" + role="img" + > + <svg + class="material-design-icon__svg" + fill="currentColor" + height="36" + viewBox="0 0 24 24" + width="36" + > + <path + d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z" + > + <!----> + </path> + </svg> + </span> + </span> + <span + class="checkbox-content__text checkbox-radio-switch__text" + data-v-e75842d8="" + > + Automatically generate a birthday calendar + </span> + </span> + </span> + <em + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Birthday calendars will be generated by a background job. + </em> + <br + data-v-0974f50a="" + data-v-6b8d4c30="" + /> + <em + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Hence they will not be available immediately after enabling but will show up after some time. + </em> + </p> + <p + data-v-0974f50a="" + data-v-6b8d4c30="" + > + <span + class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked" + data-v-0974f50a="" + data-v-6b8d4c30="" + data-v-feaabebe="" + style="--icon-size: 36px; --icon-height: 16px;" + > + <input + aria-labelledby="caldavSendEventReminders-label" + class="checkbox-radio-switch__input" + data-v-feaabebe="" + id="caldavSendEventReminders" + type="checkbox" + value="" + /> + <span + class="checkbox-content checkbox-radio-switch__content checkbox-content-switch checkbox-content--has-text" + data-v-e75842d8="" + data-v-feaabebe="" + id="caldavSendEventReminders-label" + > + <span + aria-hidden="true" + class="checkbox-content__icon checkbox-content__icon--checked checkbox-radio-switch__icon" + data-v-e75842d8="" + inert="inert" + > + <span + aria-hidden="true" + class="material-design-icon toggle-switch-icon" + data-v-e75842d8="" + role="img" + > + <svg + class="material-design-icon__svg" + fill="currentColor" + height="36" + viewBox="0 0 24 24" + width="36" + > + <path + d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z" + > + <!----> + </path> + </svg> + </span> + </span> + <span + class="checkbox-content__text checkbox-radio-switch__text" + data-v-e75842d8="" + > + Send notifications for events + </span> + </span> + </span> + <em + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Please make sure to properly set up + <a + href="../admin#mail_general_settings" + > + the email server + </a> + . + </em> + <br + data-v-0974f50a="" + data-v-6b8d4c30="" + /> + <em + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Notifications are sent via background jobs, so these must occur often enough. + </em> + </p> + <p + class="indented" + data-v-0974f50a="" + data-v-6b8d4c30="" + > + <span + class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked" + data-v-0974f50a="" + data-v-6b8d4c30="" + data-v-feaabebe="" + style="--icon-size: 36px; --icon-height: 16px;" + > + <input + aria-labelledby="caldavSendEventRemindersToSharedGroupMembers-label" + class="checkbox-radio-switch__input" + data-v-feaabebe="" + id="caldavSendEventRemindersToSharedGroupMembers" + type="checkbox" + value="" + /> + <span + class="checkbox-content checkbox-radio-switch__content checkbox-content-switch checkbox-content--has-text" + data-v-e75842d8="" + data-v-feaabebe="" + id="caldavSendEventRemindersToSharedGroupMembers-label" + > + <span + aria-hidden="true" + class="checkbox-content__icon checkbox-content__icon--checked checkbox-radio-switch__icon" + data-v-e75842d8="" + inert="inert" + > + <span + aria-hidden="true" + class="material-design-icon toggle-switch-icon" + data-v-e75842d8="" + role="img" + > + <svg + class="material-design-icon__svg" + fill="currentColor" + height="36" + viewBox="0 0 24 24" + width="36" + > + <path + d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z" + > + <!----> + </path> + </svg> + </span> + </span> + <span + class="checkbox-content__text checkbox-radio-switch__text" + data-v-e75842d8="" + > + Send reminder notifications to calendar sharees as well + </span> + </span> + </span> + <em + data-v-0974f50a="" + data-v-6b8d4c30="" + > + Reminders are always sent to organizers and attendees. + </em> + </p> + <p + class="indented" + data-v-0974f50a="" + data-v-6b8d4c30="" + > + <span + class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked" + data-v-0974f50a="" + data-v-6b8d4c30="" + data-v-feaabebe="" + style="--icon-size: 36px; --icon-height: 16px;" + > + <input + aria-labelledby="caldavSendEventRemindersPush-label" + class="checkbox-radio-switch__input" + data-v-feaabebe="" + id="caldavSendEventRemindersPush" + type="checkbox" + value="" + /> + <span + class="checkbox-content checkbox-radio-switch__content checkbox-content-switch checkbox-content--has-text" + data-v-e75842d8="" + data-v-feaabebe="" + id="caldavSendEventRemindersPush-label" + > + <span + aria-hidden="true" + class="checkbox-content__icon checkbox-content__icon--checked checkbox-radio-switch__icon" + data-v-e75842d8="" + inert="inert" + > + <span + aria-hidden="true" + class="material-design-icon toggle-switch-icon" + data-v-e75842d8="" + role="img" + > + <svg + class="material-design-icon__svg" + fill="currentColor" + height="36" + viewBox="0 0 24 24" + width="36" + > + <path + d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z" + > + <!----> + </path> + </svg> + </span> + </span> + <span + class="checkbox-content__text checkbox-radio-switch__text" + data-v-e75842d8="" + > + Enable notifications for events via push + </span> + </span> + </span> + </p> + </div> +</div> +`; exports[`CalDavSettings interactions 1`] = ` <div> 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) { diff --git a/apps/files_external/src/actions/enterCredentialsAction.spec.ts b/apps/files_external/src/actions/enterCredentialsAction.spec.ts index 518b48c264d..5d1ff05e229 100644 --- a/apps/files_external/src/actions/enterCredentialsAction.spec.ts +++ b/apps/files_external/src/actions/enterCredentialsAction.spec.ts @@ -2,10 +2,11 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { action } from './enterCredentialsAction' -import { expect } from '@jest/globals' -import { File, Folder, Permission, View, DefaultType, FileAction } from '@nextcloud/files' import type { StorageConfig } from '../services/externalStorage' + +import { File, Folder, Permission, View, DefaultType, FileAction } from '@nextcloud/files' +import { describe, expect, test } from 'vitest' +import { action } from './enterCredentialsAction' import { STORAGE_STATUS } from '../utils/credentialsUtils' const view = { @@ -36,7 +37,7 @@ describe('Enter credentials action conditions tests', () => { expect(action).toBeInstanceOf(FileAction) expect(action.id).toBe('credentials-external-storage') expect(action.displayName([storage], externalStorageView)).toBe('Enter missing credentials') - expect(action.iconSvgInline([storage], externalStorageView)).toBe('<svg>SvgMock</svg>') + expect(action.iconSvgInline([storage], externalStorageView)).toMatch(/<svg.+<\/svg>/) expect(action.default).toBe(DefaultType.DEFAULT) expect(action.order).toBe(-1000) expect(action.inline!(storage, externalStorageView)).toBe(true) diff --git a/apps/files_external/src/actions/openInFilesAction.spec.ts b/apps/files_external/src/actions/openInFilesAction.spec.ts index 83aa38f1753..aa9573eca77 100644 --- a/apps/files_external/src/actions/openInFilesAction.spec.ts +++ b/apps/files_external/src/actions/openInFilesAction.spec.ts @@ -2,10 +2,11 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { action } from './openInFilesAction' -import { expect } from '@jest/globals' import { Folder, Permission, View, DefaultType, FileAction } from '@nextcloud/files' +import { describe, expect, test, vi } from 'vitest' + import type { StorageConfig } from '../services/externalStorage' +import { action } from './openInFilesAction' import { STORAGE_STATUS } from '../utils/credentialsUtils' const view = { @@ -73,7 +74,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 } } } @@ -98,7 +99,7 @@ describe('Open in files action execute tests', () => { }) test('Open in files broken storage', async () => { - const confirmMock = jest.fn() + const confirmMock = vi.fn() // @ts-expect-error We only mock what is needed window.OC = { dialogs: { confirm: confirmMock } } diff --git a/apps/files_external/src/utils/externalStorageUtils.spec.ts b/apps/files_external/src/utils/externalStorageUtils.spec.ts index 55d3773a917..a6a29e27a7c 100644 --- a/apps/files_external/src/utils/externalStorageUtils.spec.ts +++ b/apps/files_external/src/utils/externalStorageUtils.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, Permission } from '@nextcloud/files' +import { describe, expect, test } from 'vitest' import { isNodeExternalStorage } from './externalStorageUtils' describe('Is node an external storage', () => { diff --git a/apps/files_sharing/src/actions/acceptShareAction.spec.ts b/apps/files_sharing/src/actions/acceptShareAction.spec.ts index 848bdc5496b..04199f998d0 100644 --- a/apps/files_sharing/src/actions/acceptShareAction.spec.ts +++ b/apps/files_sharing/src/actions/acceptShareAction.spec.ts @@ -2,14 +2,17 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ +import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest' + import { action } from './acceptShareAction' -import { expect } from '@jest/globals' import { File, Permission, View, FileAction } from '@nextcloud/files' import { ShareType } from '@nextcloud/sharing' -import eventBus from '@nextcloud/event-bus' +import * as eventBus from '@nextcloud/event-bus' import axios from '@nextcloud/axios' import '../main' +vi.mock('@nextcloud/axios') + const view = { id: 'files', name: 'Files', @@ -39,7 +42,7 @@ describe('Accept share action conditions tests', () => { expect(action).toBeInstanceOf(FileAction) expect(action.id).toBe('accept-share') expect(action.displayName([file], pendingShareView)).toBe('Accept share') - expect(action.iconSvgInline([file], pendingShareView)).toBe('<svg>SvgMock</svg>') + expect(action.iconSvgInline([file], pendingShareView)).toMatch(/<svg.+<\/svg>/) expect(action.default).toBeUndefined() expect(action.order).toBe(1) expect(action.inline).toBeDefined() @@ -92,9 +95,11 @@ describe('Accept share action enabled tests', () => { }) describe('Accept share action execute tests', () => { + beforeEach(() => { vi.resetAllMocks() }) + test('Accept share action', async () => { - jest.spyOn(axios, 'post') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'post') + vi.spyOn(eventBus, 'emit') const file = new File({ id: 1, @@ -112,15 +117,15 @@ describe('Accept share action execute tests', () => { expect(exec).toBe(true) expect(axios.post).toBeCalledTimes(1) - expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/123') + expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/123') expect(eventBus.emit).toBeCalledTimes(1) expect(eventBus.emit).toBeCalledWith('files:node:deleted', file) }) test('Accept remote share action', async () => { - jest.spyOn(axios, 'post') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'post') + vi.spyOn(eventBus, 'emit') const file = new File({ id: 1, @@ -139,15 +144,15 @@ describe('Accept share action execute tests', () => { expect(exec).toBe(true) expect(axios.post).toBeCalledTimes(1) - expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/123') + expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/123') expect(eventBus.emit).toBeCalledTimes(1) expect(eventBus.emit).toBeCalledWith('files:node:deleted', file) }) test('Accept share action batch', async () => { - jest.spyOn(axios, 'post') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'post') + vi.spyOn(eventBus, 'emit') const file1 = new File({ id: 1, @@ -177,8 +182,8 @@ describe('Accept share action execute tests', () => { expect(exec).toStrictEqual([true, true]) expect(axios.post).toBeCalledTimes(2) - expect(axios.post).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/123') - expect(axios.post).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/456') + expect(axios.post).toHaveBeenNthCalledWith(1, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/123') + expect(axios.post).toHaveBeenNthCalledWith(2, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/456') expect(eventBus.emit).toBeCalledTimes(2) expect(eventBus.emit).toHaveBeenNthCalledWith(1, 'files:node:deleted', file1) @@ -186,7 +191,7 @@ describe('Accept share action execute tests', () => { }) test('Accept fails', async () => { - jest.spyOn(axios, 'post').mockImplementation(() => { throw new Error('Mock error') }) + vi.spyOn(axios, 'post').mockImplementation(() => { throw new Error('Mock error') }) const file = new File({ id: 1, @@ -204,7 +209,7 @@ describe('Accept share action execute tests', () => { expect(exec).toBe(false) expect(axios.post).toBeCalledTimes(1) - expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/123') + expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/123') expect(eventBus.emit).toBeCalledTimes(0) }) diff --git a/apps/files_sharing/src/actions/openInFilesAction.spec.ts b/apps/files_sharing/src/actions/openInFilesAction.spec.ts index e7e447ad218..36e4b7ae3c9 100644 --- a/apps/files_sharing/src/actions/openInFilesAction.spec.ts +++ b/apps/files_sharing/src/actions/openInFilesAction.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, DefaultType, FileAction } from '@nextcloud/files' +import { describe, expect, test, vi } from 'vitest' import '../main' import { action } from './openInFilesAction' @@ -56,7 +56,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 } } } diff --git a/apps/files_sharing/src/actions/rejectShareAction.spec.ts b/apps/files_sharing/src/actions/rejectShareAction.spec.ts index e4d37cd952c..51ded69d1c5 100644 --- a/apps/files_sharing/src/actions/rejectShareAction.spec.ts +++ b/apps/files_sharing/src/actions/rejectShareAction.spec.ts @@ -2,14 +2,17 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { action } from './rejectShareAction' -import { expect } from '@jest/globals' import { File, Folder, Permission, View, FileAction } from '@nextcloud/files' +import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest' import { ShareType } from '@nextcloud/sharing' -import eventBus from '@nextcloud/event-bus' +import * as eventBus from '@nextcloud/event-bus' import axios from '@nextcloud/axios' + +import { action } from './rejectShareAction' import '../main' +vi.mock('@nextcloud/axios') + const view = { id: 'files', name: 'Files', @@ -39,7 +42,7 @@ describe('Reject share action conditions tests', () => { expect(action).toBeInstanceOf(FileAction) expect(action.id).toBe('reject-share') expect(action.displayName([file], pendingShareView)).toBe('Reject share') - expect(action.iconSvgInline([file], pendingShareView)).toBe('<svg>SvgMock</svg>') + expect(action.iconSvgInline([file], pendingShareView)).toMatch(/<svg.+<\/svg>/) expect(action.default).toBeUndefined() expect(action.order).toBe(2) expect(action.inline).toBeDefined() @@ -119,9 +122,11 @@ describe('Reject share action enabled tests', () => { }) describe('Reject share action execute tests', () => { + beforeEach(() => { vi.resetAllMocks() }) + test('Reject share action', async () => { - jest.spyOn(axios, 'delete') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'delete') + vi.spyOn(eventBus, 'emit') const file = new File({ id: 1, @@ -139,15 +144,15 @@ describe('Reject share action execute tests', () => { expect(exec).toBe(true) expect(axios.delete).toBeCalledTimes(1) - expect(axios.delete).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/123') + expect(axios.delete).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/123') expect(eventBus.emit).toBeCalledTimes(1) expect(eventBus.emit).toBeCalledWith('files:node:deleted', file) }) test('Reject remote share action', async () => { - jest.spyOn(axios, 'delete') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'delete') + vi.spyOn(eventBus, 'emit') const file = new File({ id: 1, @@ -166,15 +171,15 @@ describe('Reject share action execute tests', () => { expect(exec).toBe(true) expect(axios.delete).toBeCalledTimes(1) - expect(axios.delete).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/123') + expect(axios.delete).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/123') expect(eventBus.emit).toBeCalledTimes(1) expect(eventBus.emit).toBeCalledWith('files:node:deleted', file) }) test('Reject share action batch', async () => { - jest.spyOn(axios, 'delete') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'delete') + vi.spyOn(eventBus, 'emit') const file1 = new File({ id: 1, @@ -204,8 +209,8 @@ describe('Reject share action execute tests', () => { expect(exec).toStrictEqual([true, true]) expect(axios.delete).toBeCalledTimes(2) - expect(axios.delete).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/123') - expect(axios.delete).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/456') + expect(axios.delete).toHaveBeenNthCalledWith(1, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/123') + expect(axios.delete).toHaveBeenNthCalledWith(2, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/456') expect(eventBus.emit).toBeCalledTimes(2) expect(eventBus.emit).toHaveBeenNthCalledWith(1, 'files:node:deleted', file1) @@ -213,7 +218,7 @@ describe('Reject share action execute tests', () => { }) test('Reject fails', async () => { - jest.spyOn(axios, 'delete').mockImplementation(() => { throw new Error('Mock error') }) + vi.spyOn(axios, 'delete').mockImplementation(() => { throw new Error('Mock error') }) const file = new File({ id: 1, @@ -231,7 +236,7 @@ describe('Reject share action execute tests', () => { expect(exec).toBe(false) expect(axios.delete).toBeCalledTimes(1) - expect(axios.delete).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/123') + expect(axios.delete).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/123') expect(eventBus.emit).toBeCalledTimes(0) }) diff --git a/apps/files_sharing/src/actions/restoreShareAction.spec.ts b/apps/files_sharing/src/actions/restoreShareAction.spec.ts index 8132c76fe2b..d6628810064 100644 --- a/apps/files_sharing/src/actions/restoreShareAction.spec.ts +++ b/apps/files_sharing/src/actions/restoreShareAction.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 './restoreShareAction' -import { expect } from '@jest/globals' import { File, Permission, View, FileAction } from '@nextcloud/files' import { ShareType } from '@nextcloud/sharing' -import eventBus from '@nextcloud/event-bus' +import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest' + import axios from '@nextcloud/axios' +import * as eventBus from '@nextcloud/event-bus' +import { action } from './restoreShareAction' import '../main' +vi.mock('@nextcloud/auth') +vi.mock('@nextcloud/axios') + const view = { id: 'files', name: 'Files', @@ -39,7 +43,7 @@ describe('Restore share action conditions tests', () => { expect(action).toBeInstanceOf(FileAction) expect(action.id).toBe('restore-share') expect(action.displayName([file], deletedShareView)).toBe('Restore share') - expect(action.iconSvgInline([file], deletedShareView)).toBe('<svg>SvgMock</svg>') + expect(action.iconSvgInline([file], deletedShareView)).toMatch(/<svg.+<\/svg>/) expect(action.default).toBeUndefined() expect(action.order).toBe(1) expect(action.inline).toBeDefined() @@ -92,9 +96,11 @@ describe('Restore share action enabled tests', () => { }) describe('Restore share action execute tests', () => { + beforeEach(() => { vi.resetAllMocks() }) + test('Restore share action', async () => { - jest.spyOn(axios, 'post') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'post') + vi.spyOn(eventBus, 'emit') const file = new File({ id: 1, @@ -112,15 +118,15 @@ describe('Restore share action execute tests', () => { expect(exec).toBe(true) expect(axios.post).toBeCalledTimes(1) - expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/123') + expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/123') expect(eventBus.emit).toBeCalledTimes(1) expect(eventBus.emit).toBeCalledWith('files:node:deleted', file) }) test('Restore share action batch', async () => { - jest.spyOn(axios, 'post') - jest.spyOn(eventBus, 'emit') + vi.spyOn(axios, 'post') + vi.spyOn(eventBus, 'emit') const file1 = new File({ id: 1, @@ -150,8 +156,8 @@ describe('Restore share action execute tests', () => { expect(exec).toStrictEqual([true, true]) expect(axios.post).toBeCalledTimes(2) - expect(axios.post).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/123') - expect(axios.post).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/456') + expect(axios.post).toHaveBeenNthCalledWith(1, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/123') + expect(axios.post).toHaveBeenNthCalledWith(2, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/456') expect(eventBus.emit).toBeCalledTimes(2) expect(eventBus.emit).toHaveBeenNthCalledWith(1, 'files:node:deleted', file1) @@ -159,7 +165,8 @@ describe('Restore share action execute tests', () => { }) test('Restore fails', async () => { - jest.spyOn(axios, 'post').mockImplementation(() => { throw new Error('Mock error') }) + vi.spyOn(axios, 'post') + .mockImplementation(() => { throw new Error('Mock error') }) const file = new File({ id: 1, @@ -177,7 +184,7 @@ describe('Restore share action execute tests', () => { expect(exec).toBe(false) expect(axios.post).toBeCalledTimes(1) - expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/123') + expect(axios.post).toBeCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/123') expect(eventBus.emit).toBeCalledTimes(0) }) diff --git a/apps/files_sharing/src/lib/SharePermissionsToolBox.spec.js b/apps/files_sharing/src/lib/SharePermissionsToolBox.spec.js index 9ca770a0ac5..a58552063d8 100644 --- a/apps/files_sharing/src/lib/SharePermissionsToolBox.spec.js +++ b/apps/files_sharing/src/lib/SharePermissionsToolBox.spec.js @@ -2,6 +2,7 @@ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ +import { describe, expect, test } from 'vitest' import { ATOMIC_PERMISSIONS, diff --git a/apps/files_sharing/src/services/SharingService.spec.ts b/apps/files_sharing/src/services/SharingService.spec.ts index ba0591a765a..bd0e018db7a 100644 --- a/apps/files_sharing/src/services/SharingService.spec.ts +++ b/apps/files_sharing/src/services/SharingService.spec.ts @@ -3,29 +3,35 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import type { OCSResponse } from '@nextcloud/typings/ocs' -import { expect } from '@jest/globals' -import { Type } from '@nextcloud/sharing' -import * as auth from '@nextcloud/auth' -import axios from '@nextcloud/axios' -import { getContents } from './SharingService' import { File, Folder } from '@nextcloud/files' +import { ShareType } from '@nextcloud/sharing' +import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest' + +import { getContents } from './SharingService' +import * as auth from '@nextcloud/auth' import logger from './logger' -window.OC = { - ...window.OC, - TAG_FAVORITE: '_$!<Favorite>!$_', -} +const TAG_FAVORITE = '_$!<Favorite>!$_' + +const axios = vi.hoisted(() => ({ get: vi.fn() })) +vi.mock('@nextcloud/auth') +vi.mock('@nextcloud/axios', () => ({ default: axios })) -// Mock webroot variable +// Mock web root variable beforeAll(() => { + window.OC = { + ...window.OC, + TAG_FAVORITE, + } // eslint-disable-next-line @typescript-eslint/no-explicit-any - (window as any)._oc_webroot = '' + ;(window as any)._oc_webroot = '' }) describe('SharingService methods definitions', () => { - beforeAll(() => { - jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { + beforeEach(() => { + vi.resetAllMocks() + axios.get.mockImplementation(async (): Promise<unknown> => { return { data: { ocs: { @@ -36,20 +42,16 @@ describe('SharingService methods definitions', () => { }, data: [], }, - } as OCSResponse<any>, + } as OCSResponse, } }) }) - afterAll(() => { - jest.restoreAllMocks() - }) - test('Shared with you', async () => { await getContents(true, false, false, false, []) expect(axios.get).toHaveBeenCalledTimes(2) - expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', { + expect(axios.get).toHaveBeenNthCalledWith(1, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares', { headers: { 'Content-Type': 'application/json', }, @@ -58,7 +60,7 @@ describe('SharingService methods definitions', () => { include_tags: true, }, }) - expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares', { + expect(axios.get).toHaveBeenNthCalledWith(2, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/remote_shares', { headers: { 'Content-Type': 'application/json', }, @@ -72,7 +74,7 @@ describe('SharingService methods definitions', () => { await getContents(false, true, false, false, []) expect(axios.get).toHaveBeenCalledTimes(1) - expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', { + expect(axios.get).toHaveBeenCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares', { headers: { 'Content-Type': 'application/json', }, @@ -87,7 +89,7 @@ describe('SharingService methods definitions', () => { await getContents(false, false, true, false, []) expect(axios.get).toHaveBeenCalledTimes(2) - expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending', { + expect(axios.get).toHaveBeenNthCalledWith(1, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares/pending', { headers: { 'Content-Type': 'application/json', }, @@ -95,7 +97,7 @@ describe('SharingService methods definitions', () => { include_tags: true, }, }) - expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending', { + expect(axios.get).toHaveBeenNthCalledWith(2, 'http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending', { headers: { 'Content-Type': 'application/json', }, @@ -109,7 +111,7 @@ describe('SharingService methods definitions', () => { await getContents(false, true, false, false, []) expect(axios.get).toHaveBeenCalledTimes(1) - expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', { + expect(axios.get).toHaveBeenCalledWith('http://nextcloud.local/ocs/v2.php/apps/files_sharing/api/v1/shares', { headers: { 'Content-Type': 'application/json', }, @@ -121,7 +123,7 @@ describe('SharingService methods definitions', () => { }) test('Unknown owner', async () => { - jest.spyOn(auth, 'getCurrentUser').mockReturnValue(null) + vi.spyOn(auth, 'getCurrentUser').mockReturnValue(null) const results = await getContents(false, true, false, false, []) expect(results.folder.owner).toEqual(null) @@ -129,8 +131,9 @@ describe('SharingService methods definitions', () => { }) describe('SharingService filtering', () => { - beforeAll(() => { - jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { + beforeEach(() => { + vi.resetAllMocks() + axios.get.mockImplementation(async (): Promise<unknown> => { return { data: { ocs: { @@ -142,7 +145,7 @@ describe('SharingService filtering', () => { data: [ { id: '62', - share_type: Type.SHARE_TYPE_USER, + share_type: ShareType.User, uid_owner: 'test', displayname_owner: 'test', permissions: 31, @@ -168,12 +171,8 @@ describe('SharingService filtering', () => { }) }) - afterAll(() => { - jest.restoreAllMocks() - }) - test('Shared with others filtering', async () => { - const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_USER]) + const shares = await getContents(false, true, false, false, [ShareType.User]) expect(axios.get).toHaveBeenCalledTimes(1) expect(shares.contents).toHaveLength(1) @@ -182,7 +181,7 @@ describe('SharingService filtering', () => { }) test('Shared with others filtering empty', async () => { - const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_LINK]) + const shares = await getContents(false, true, false, false, [ShareType.Link]) expect(axios.get).toHaveBeenCalledTimes(1) expect(shares.contents).toHaveLength(0) @@ -275,11 +274,13 @@ describe('SharingService share to Node mapping', () => { mail_send: 0, hide_download: 0, attributes: null, - tags: [window.OC.TAG_FAVORITE], + tags: [TAG_FAVORITE], } + beforeEach(() => { vi.resetAllMocks() }) + test('File', async () => { - jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + axios.get.mockReturnValueOnce(Promise.resolve({ data: { ocs: { data: [shareFile], @@ -295,7 +296,7 @@ describe('SharingService share to Node mapping', () => { const file = shares.contents[0] as File expect(file).toBeInstanceOf(File) expect(file.fileid).toBe(530936) - expect(file.source).toBe('http://localhost/remote.php/dav/files/test/document.md') + expect(file.source).toBe('http://nextcloud.local/remote.php/dav/files/test/document.md') expect(file.owner).toBe('test') expect(file.mime).toBe('text/markdown') expect(file.mtime).toBeInstanceOf(Date) @@ -308,7 +309,7 @@ describe('SharingService share to Node mapping', () => { }) test('Folder', async () => { - jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + axios.get.mockReturnValueOnce(Promise.resolve({ data: { ocs: { data: [shareFolder], @@ -324,7 +325,7 @@ describe('SharingService share to Node mapping', () => { const folder = shares.contents[0] as Folder expect(folder).toBeInstanceOf(Folder) expect(folder.fileid).toBe(531080) - expect(folder.source).toBe('http://localhost/remote.php/dav/files/test/Folder') + expect(folder.source).toBe('http://nextcloud.local/remote.php/dav/files/test/Folder') expect(folder.owner).toBe('test') expect(folder.mime).toBe('httpd/unix-directory') expect(folder.mtime).toBeInstanceOf(Date) @@ -338,8 +339,8 @@ describe('SharingService share to Node mapping', () => { }) test('Empty', async () => { - jest.spyOn(logger, 'error').mockImplementationOnce(() => {}) - jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + vi.spyOn(logger, 'error').mockImplementationOnce(() => {}) + axios.get.mockReturnValueOnce(Promise.resolve({ data: { ocs: { data: [], @@ -353,8 +354,8 @@ describe('SharingService share to Node mapping', () => { }) test('Error', async () => { - jest.spyOn(logger, 'error').mockImplementationOnce(() => {}) - jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + vi.spyOn(logger, 'error').mockImplementationOnce(() => {}) + axios.get.mockReturnValueOnce(Promise.resolve({ data: { ocs: { data: [null], diff --git a/apps/files_sharing/src/views/shares.spec.ts b/apps/files_sharing/src/views/shares.spec.ts index 13e1f1f97e5..153057bc0ad 100644 --- a/apps/files_sharing/src/views/shares.spec.ts +++ b/apps/files_sharing/src/views/shares.spec.ts @@ -4,8 +4,8 @@ */ /* eslint-disable n/no-extraneous-import */ import type { OCSResponse } from '@nextcloud/typings/ocs' -import { expect } from '@jest/globals' import { Folder, Navigation, View, getNavigation } from '@nextcloud/files' +import { beforeEach, describe, expect, test, vi } from 'vitest' import axios from '@nextcloud/axios' import '../main' @@ -20,16 +20,13 @@ declare global { describe('Sharing views definition', () => { let Navigation beforeEach(() => { + delete window._nc_navigation Navigation = getNavigation() expect(window._nc_navigation).toBeDefined() }) - afterAll(() => { - delete window._nc_navigation - }) - test('Default values', () => { - jest.spyOn(Navigation, 'register') + vi.spyOn(Navigation, 'register') expect(Navigation.views.length).toBe(0) @@ -47,7 +44,7 @@ describe('Sharing views definition', () => { expect(shareOverviewView?.id).toBe('shareoverview') expect(shareOverviewView?.name).toBe('Shares') expect(shareOverviewView?.caption).toBe('Overview of shared files.') - expect(shareOverviewView?.icon).toBe('<svg>SvgMock</svg>') + expect(shareOverviewView?.icon).toMatch(/<svg.+<\/svg>/i) expect(shareOverviewView?.order).toBe(20) expect(shareOverviewView?.columns).toStrictEqual([]) expect(shareOverviewView?.getContents).toBeDefined() @@ -68,7 +65,7 @@ describe('Sharing views definition', () => { expect(view?.caption).toBeDefined() expect(view?.emptyTitle).toBeDefined() expect(view?.emptyCaption).toBeDefined() - expect(view?.icon).toBe('<svg>SvgMock</svg>') + expect(view?.icon).match(/<svg.+<\/svg>/) expect(view?.order).toBe(index + 1) expect(view?.columns).toStrictEqual([]) expect(view?.getContents).toBeDefined() @@ -79,16 +76,13 @@ describe('Sharing views definition', () => { describe('Sharing views contents', () => { let Navigation beforeEach(() => { + delete window._nc_navigation Navigation = getNavigation() expect(window._nc_navigation).toBeDefined() }) - afterAll(() => { - delete window._nc_navigation - }) - test('Sharing overview get contents', async () => { - jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { + vi.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { return { data: { ocs: { diff --git a/apps/settings/src/utils/appDiscoverParser.spec.ts b/apps/settings/src/utils/appDiscoverParser.spec.ts index f025b1346fb..2a631014679 100644 --- a/apps/settings/src/utils/appDiscoverParser.spec.ts +++ b/apps/settings/src/utils/appDiscoverParser.spec.ts @@ -5,7 +5,7 @@ import type { IAppDiscoverElement } from '../constants/AppDiscoverTypes' -import { describe, expect, it } from '@jest/globals' +import { describe, expect, it } from 'vitest' import { filterElements, parseApiResponse } from './appDiscoverParser' describe('App Discover API parser', () => { diff --git a/apps/systemtags/src/files_actions/inlineSystemTagsAction.spec.ts b/apps/systemtags/src/files_actions/inlineSystemTagsAction.spec.ts index 61353d098d7..9d25bfcd2ad 100644 --- a/apps/systemtags/src/files_actions/inlineSystemTagsAction.spec.ts +++ b/apps/systemtags/src/files_actions/inlineSystemTagsAction.spec.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import { action } from './inlineSystemTagsAction' -import { expect } from '@jest/globals' +import { describe, expect, test } from 'vitest' import { File, Permission, View, FileAction } from '@nextcloud/files' const view = { diff --git a/apps/systemtags/src/files_actions/openInFilesAction.spec.ts b/apps/systemtags/src/files_actions/openInFilesAction.spec.ts index e97e3872239..43f8dbbb9f4 100644 --- a/apps/systemtags/src/files_actions/openInFilesAction.spec.ts +++ b/apps/systemtags/src/files_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 = { @@ -79,7 +79,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 } } } @@ -101,7 +101,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/systemtags/src/utils.spec.ts b/apps/systemtags/src/utils.spec.ts index e51473bf2f4..a43d6db8ca6 100644 --- a/apps/systemtags/src/utils.spec.ts +++ b/apps/systemtags/src/utils.spec.ts @@ -5,8 +5,8 @@ import type { DAVResultResponseProps } from 'webdav' import type { ServerTag, Tag } from './types.js' +import { describe, expect, it } from 'vitest' -import { describe, it, expect } from '@jest/globals' import { formatTag, parseIdFromLocation, parseTags } from './utils' describe('systemtags - utils', () => { diff --git a/core/src/tests/OC/requesttoken.spec.js b/core/src/tests/OC/requesttoken.spec.js index 456b304df56..36833742d14 100644 --- a/core/src/tests/OC/requesttoken.spec.js +++ b/core/src/tests/OC/requesttoken.spec.js @@ -3,10 +3,12 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { subscribe, unsubscribe } from '@nextcloud/event-bus' - +import { beforeEach, describe, expect, test, vi } from 'vitest' import { manageToken, setToken } from '../../OC/requesttoken.js' +const eventbus = vi.hoisted(() => ({ emit: vi.fn() })) +vi.mock('@nextcloud/event-bus', () => eventbus) + describe('request token', () => { let emit @@ -14,7 +16,7 @@ describe('request token', () => { const token = 'abc123' beforeEach(() => { - emit = jest.fn() + emit = vi.fn() const head = window.document.getElementsByTagName('head')[0] head.setAttribute('data-requesttoken', token) @@ -32,22 +34,10 @@ describe('request token', () => { }) describe('@nextcloud/auth integration', () => { - let listener - - beforeEach(() => { - listener = jest.fn() - - subscribe('csrf-token-update', listener) - }) - - afterEach(() => { - unsubscribe('csrf-token-update', listener) - }) - test('fires off an event for @nextcloud/auth', () => { setToken('123') - expect(listener).toHaveBeenCalledWith({ token: '123' }) + expect(eventbus.emit).toHaveBeenCalledWith('csrf-token-update', { token: '123' }) }) }) diff --git a/core/src/tests/components/ContactsMenu/Contact.spec.js b/core/src/tests/components/ContactsMenu/Contact.spec.js index bf474505009..e83f75bfd15 100644 --- a/core/src/tests/components/ContactsMenu/Contact.spec.js +++ b/core/src/tests/components/ContactsMenu/Contact.spec.js @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import { describe, expect, it } from 'vitest' import { shallowMount } from '@vue/test-utils' import Contact from '../../../components/ContactsMenu/Contact.vue' diff --git a/core/src/tests/views/ContactsMenu.spec.js b/core/src/tests/views/ContactsMenu.spec.js index 6df73fa1827..084c3215e47 100644 --- a/core/src/tests/views/ContactsMenu.spec.js +++ b/core/src/tests/views/ContactsMenu.spec.js @@ -3,13 +3,18 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import axios from '@nextcloud/axios' import { mount, shallowMount } from '@vue/test-utils' +import { describe, expect, it, vi } from 'vitest' import ContactsMenu from '../../views/ContactsMenu.vue' -jest.mock('@nextcloud/axios', () => ({ - post: jest.fn(), +const axios = vi.hoisted(() => ({ + post: vi.fn(), +})) +vi.mock('@nextcloud/axios', () => ({ default: axios })) + +vi.mock('@nextcloud/auth', () => ({ + getCurrentUser: () => ({ uid: 'user', isAdmin: false, displayName: 'User' }), })) describe('ContactsMenu', function() { @@ -39,7 +44,7 @@ describe('ContactsMenu', function() { it('shows error view when contacts can not be loaded', async () => { const view = mount(ContactsMenu) axios.post.mockResolvedValue({}) - jest.spyOn(console, 'error').mockImplementation(() => {}) + vi.spyOn(console, 'error').mockImplementation(() => {}) try { await view.vm.handleOpen() @@ -56,7 +61,7 @@ describe('ContactsMenu', function() { it('shows text when there are no contacts', async () => { const view = mount(ContactsMenu) - axios.post.mockResolvedValue({ + axios.post.mockResolvedValueOnce({ data: { contacts: [], contactsAppEnabled: false, |