From 2a8c20b946d6552b4901b6c921cd9d06fafce4d4 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 24 Nov 2025 16:23:02 +0100 Subject: [PATCH] chore: adjust vitest infrastructure to properly run both suits Signed-off-by: Ferdinand Thiessen --- __mocks__ | 1 + __tests__ | 1 + .../src/files_actions/restoreAction.spec.ts | 4 +- .../emptyTrashAction.spec.ts | 32 ++++++--- build/frontend-legacy/vitest.config.mts | 9 ++- .../frontend/__mocks__}/@nextcloud/auth.ts | 0 .../frontend/__mocks__}/@nextcloud/axios.ts | 0 .../__mocks__}/@nextcloud/capabilities.ts | 0 .../frontend/__mocks__}/@nextcloud/dialogs.ts | 0 .../__mocks__}/@nextcloud/initial-state.ts | 0 .../frontend/__mocks__}/css.js | 0 .../frontend/__mocks__}/svg.js | 0 .../frontend/__mocks__}/webdav.ts | 0 .../frontend/__tests__}/FileSystemAPIUtils.ts | 0 .../frontend/__tests__}/mock-window.js | 0 .../frontend/__tests__}/setup-global.js | 0 .../__tests__}/setup-testing-library.js | 0 build/frontend/package.json | 8 +-- build/frontend/vitest.config.ts | 66 +++++++++++++++++++ package.json | 8 +-- vitest.config.ts | 56 +--------------- 21 files changed, 111 insertions(+), 74 deletions(-) create mode 120000 __mocks__ create mode 120000 __tests__ rename {__mocks__ => build/frontend/__mocks__}/@nextcloud/auth.ts (100%) rename {__mocks__ => build/frontend/__mocks__}/@nextcloud/axios.ts (100%) rename {__mocks__ => build/frontend/__mocks__}/@nextcloud/capabilities.ts (100%) rename {__mocks__ => build/frontend/__mocks__}/@nextcloud/dialogs.ts (100%) rename {__mocks__ => build/frontend/__mocks__}/@nextcloud/initial-state.ts (100%) rename {__mocks__ => build/frontend/__mocks__}/css.js (100%) rename {__mocks__ => build/frontend/__mocks__}/svg.js (100%) rename {__mocks__ => build/frontend/__mocks__}/webdav.ts (100%) rename {__tests__ => build/frontend/__tests__}/FileSystemAPIUtils.ts (100%) rename {__tests__ => build/frontend/__tests__}/mock-window.js (100%) rename {__tests__ => build/frontend/__tests__}/setup-global.js (100%) rename {__tests__ => build/frontend/__tests__}/setup-testing-library.js (100%) create mode 100644 build/frontend/vitest.config.ts diff --git a/__mocks__ b/__mocks__ new file mode 120000 index 00000000000..4d8638b2ec2 --- /dev/null +++ b/__mocks__ @@ -0,0 +1 @@ +build/frontend/__mocks__ \ No newline at end of file diff --git a/__tests__ b/__tests__ new file mode 120000 index 00000000000..10e14ddefa5 --- /dev/null +++ b/__tests__ @@ -0,0 +1 @@ +build/frontend/__tests__ \ No newline at end of file diff --git a/apps/files_trashbin/src/files_actions/restoreAction.spec.ts b/apps/files_trashbin/src/files_actions/restoreAction.spec.ts index 87f8098fa14..6ded363b134 100644 --- a/apps/files_trashbin/src/files_actions/restoreAction.spec.ts +++ b/apps/files_trashbin/src/files_actions/restoreAction.spec.ts @@ -22,7 +22,9 @@ vi.mock('@nextcloud/axios', async (origial) => ({ ...(await origial()), default: vi.mock('@nextcloud/auth') const errorSpy = vi.spyOn(window.console, 'error').mockImplementation(() => {}) -beforeEach(() => errorSpy.mockClear()) +beforeEach(() => { + vi.resetAllMocks() +}) describe('files_trashbin: file actions - restore action', () => { it('has id set', () => { diff --git a/apps/files_trashbin/src/files_listActions/emptyTrashAction.spec.ts b/apps/files_trashbin/src/files_listActions/emptyTrashAction.spec.ts index 54316ced872..c53d14b68fa 100644 --- a/apps/files_trashbin/src/files_listActions/emptyTrashAction.spec.ts +++ b/apps/files_trashbin/src/files_listActions/emptyTrashAction.spec.ts @@ -6,12 +6,24 @@ import * as ncDialogs from '@nextcloud/dialogs' import * as ncEventBus from '@nextcloud/event-bus' import { Folder } from '@nextcloud/files' -import * as ncInitialState from '@nextcloud/initial-state' import { beforeEach, describe, expect, it, vi } from 'vitest' import { trashbinView } from '../files_views/trashbinView.ts' import * as api from '../services/api.ts' import { emptyTrashAction } from './emptyTrashAction.ts' +const loadState = vi.hoisted(() => vi.fn((app, key, fallback) => { + if (fallback) { + return fallback + } + throw new Error() +})) + +vi.mock('@nextcloud/initial-state', () => ({ + loadState, +})) + +beforeEach(() => vi.resetAllMocks()) + describe('files_trashbin: file list actions - empty trashbin', () => { it('has id set', () => { expect(emptyTrashAction.id).toBe('empty-trash') @@ -27,7 +39,7 @@ describe('files_trashbin: file list actions - empty trashbin', () => { }) it('is enabled on trashbin view', () => { - const spy = vi.spyOn(ncInitialState, 'loadState').mockImplementationOnce(() => ({ allow_delete: true })) + loadState.mockImplementation(() => ({ allow_delete: true })) const root = new Folder({ owner: 'test', source: 'https://example.com/remote.php/dav/trashbin/test/', root: '/trashbin/test/' }) const nodes = [ @@ -36,12 +48,12 @@ describe('files_trashbin: file list actions - empty trashbin', () => { expect(emptyTrashAction.enabled).toBeTypeOf('function') expect(emptyTrashAction.enabled!(trashbinView, nodes, root)).toBe(true) - expect(spy).toHaveBeenCalled() - expect(spy).toHaveBeenCalledWith('files_trashbin', 'config') + expect(loadState).toHaveBeenCalled() + expect(loadState).toHaveBeenCalledWith('files_trashbin', 'config') }) it('is not enabled on another view enabled', () => { - vi.spyOn(ncInitialState, 'loadState').mockImplementationOnce(() => ({ allow_delete: true })) + loadState.mockImplementation(() => ({ allow_delete: true })) const root = new Folder({ owner: 'test', source: 'https://example.com/remote.php/dav/trashbin/test/', root: '/trashbin/test/' }) const nodes = [ @@ -62,7 +74,7 @@ describe('files_trashbin: file list actions - empty trashbin', () => { }) it('is not enabled when deletion is forbidden', () => { - const spy = vi.spyOn(ncInitialState, 'loadState').mockImplementationOnce(() => ({ allow_delete: false })) + loadState.mockImplementation(() => ({ allow_delete: false })) const root = new Folder({ owner: 'test', source: 'https://example.com/remote.php/dav/trashbin/test/', root: '/trashbin/test/' }) const nodes = [ @@ -71,13 +83,12 @@ describe('files_trashbin: file list actions - empty trashbin', () => { expect(emptyTrashAction.enabled).toBeTypeOf('function') expect(emptyTrashAction.enabled!(trashbinView, nodes, root)).toBe(false) - expect(spy).toHaveBeenCalled() - expect(spy).toHaveBeenCalledWith('files_trashbin', 'config') + expect(loadState).toHaveBeenCalled() + expect(loadState).toHaveBeenCalledWith('files_trashbin', 'config') }) it('is not enabled when not in trashbin root', () => { - vi.spyOn(ncInitialState, 'loadState').mockImplementationOnce(() => ({ allow_delete: true })) - + loadState.mockImplementation(() => ({ allow_delete: true })) const root = new Folder({ owner: 'test', source: 'https://example.com/remote.php/dav/trashbin/test/other-folder', root: '/trashbin/test/' }) const nodes = [ new Folder({ owner: 'test', source: 'https://example.com/remote.php/dav/trashbin/test/folder', root: '/trashbin/test/' }), @@ -101,6 +112,7 @@ describe('files_trashbin: file list actions - empty trashbin', () => { } beforeEach(() => { + vi.resetAllMocks() dialogBuilder = { setSeverity: vi.fn(() => dialogBuilder), setText: vi.fn(() => dialogBuilder), diff --git a/build/frontend-legacy/vitest.config.mts b/build/frontend-legacy/vitest.config.mts index feb47773e1a..645346de547 100644 --- a/build/frontend-legacy/vitest.config.mts +++ b/build/frontend-legacy/vitest.config.mts @@ -7,6 +7,7 @@ import vue from '@vitejs/plugin-vue2' import { exec } from 'node:child_process' import { resolve } from 'node:path' import { promisify } from 'node:util' +import { nodePolyfills } from 'vite-plugin-node-polyfills' import { defaultExclude, defineConfig } from 'vitest/config' const gitIgnore: string[] = [] @@ -26,7 +27,13 @@ try { } export default defineConfig({ - plugins: [vue()], + plugins: [ + nodePolyfills({ + include: ['fs', 'path'], + protocolImports: false, + }), + vue(), + ], root: import.meta.dirname, resolve: { preserveSymlinks: true, diff --git a/__mocks__/@nextcloud/auth.ts b/build/frontend/__mocks__/@nextcloud/auth.ts similarity index 100% rename from __mocks__/@nextcloud/auth.ts rename to build/frontend/__mocks__/@nextcloud/auth.ts diff --git a/__mocks__/@nextcloud/axios.ts b/build/frontend/__mocks__/@nextcloud/axios.ts similarity index 100% rename from __mocks__/@nextcloud/axios.ts rename to build/frontend/__mocks__/@nextcloud/axios.ts diff --git a/__mocks__/@nextcloud/capabilities.ts b/build/frontend/__mocks__/@nextcloud/capabilities.ts similarity index 100% rename from __mocks__/@nextcloud/capabilities.ts rename to build/frontend/__mocks__/@nextcloud/capabilities.ts diff --git a/__mocks__/@nextcloud/dialogs.ts b/build/frontend/__mocks__/@nextcloud/dialogs.ts similarity index 100% rename from __mocks__/@nextcloud/dialogs.ts rename to build/frontend/__mocks__/@nextcloud/dialogs.ts diff --git a/__mocks__/@nextcloud/initial-state.ts b/build/frontend/__mocks__/@nextcloud/initial-state.ts similarity index 100% rename from __mocks__/@nextcloud/initial-state.ts rename to build/frontend/__mocks__/@nextcloud/initial-state.ts diff --git a/__mocks__/css.js b/build/frontend/__mocks__/css.js similarity index 100% rename from __mocks__/css.js rename to build/frontend/__mocks__/css.js diff --git a/__mocks__/svg.js b/build/frontend/__mocks__/svg.js similarity index 100% rename from __mocks__/svg.js rename to build/frontend/__mocks__/svg.js diff --git a/__mocks__/webdav.ts b/build/frontend/__mocks__/webdav.ts similarity index 100% rename from __mocks__/webdav.ts rename to build/frontend/__mocks__/webdav.ts diff --git a/__tests__/FileSystemAPIUtils.ts b/build/frontend/__tests__/FileSystemAPIUtils.ts similarity index 100% rename from __tests__/FileSystemAPIUtils.ts rename to build/frontend/__tests__/FileSystemAPIUtils.ts diff --git a/__tests__/mock-window.js b/build/frontend/__tests__/mock-window.js similarity index 100% rename from __tests__/mock-window.js rename to build/frontend/__tests__/mock-window.js diff --git a/__tests__/setup-global.js b/build/frontend/__tests__/setup-global.js similarity index 100% rename from __tests__/setup-global.js rename to build/frontend/__tests__/setup-global.js diff --git a/__tests__/setup-testing-library.js b/build/frontend/__tests__/setup-testing-library.js similarity index 100% rename from __tests__/setup-testing-library.js rename to build/frontend/__tests__/setup-testing-library.js diff --git a/build/frontend/package.json b/build/frontend/package.json index 0c0a7d5149b..e954a063f4c 100644 --- a/build/frontend/package.json +++ b/build/frontend/package.json @@ -11,10 +11,10 @@ "dev": "NODE_ENV=development vite build --mode development", "lint": "eslint --suppressions-location ../eslint-baseline.json --no-error-on-unmatched-pattern ./apps/*/ ./core/", "lint:fix": "eslint --suppressions-location ../eslint-baseline.json --fix --no-error-on-unmatched-pattern ./apps/*/ ./core/", - "test": "vitest -c ../../vitest.config.ts run", - "test:coverage": "vitest -c ../../vitest.config.ts run --coverage --reporter=default", - "test:update-snapshots": "vitest -c ../../vitest.config.ts run --update", - "test:watch": "vitest -c ../../vitest.config.ts watch", + "test": "vitest run", + "test:coverage": "vitest run --coverage --reporter=default", + "test:update-snapshots": "vitest run --update", + "test:watch": "vitest watch", "watch": "NODE_ENV=development vite build --mode development --watch" }, "browserslist": [ diff --git a/build/frontend/vitest.config.ts b/build/frontend/vitest.config.ts new file mode 100644 index 00000000000..5f161c3c7fa --- /dev/null +++ b/build/frontend/vitest.config.ts @@ -0,0 +1,66 @@ +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: CC0-1.0 + */ + +import vue from '@vitejs/plugin-vue' +import { exec } from 'node:child_process' +import { resolve } from 'node:path' +import { promisify } from 'node:util' +import { defaultExclude, defineConfig } from 'vitest/config' + +const gitIgnore: string[] = [] +// get all files ignored in the apps directory (e.g. if putting `view` app there). +try { + const execAsync = promisify(exec) + const { stdout } = await execAsync('git check-ignore apps/*', { cwd: __dirname }) + gitIgnore.push(...stdout.split('\n').filter(Boolean)) + // eslint-disable-next-line no-console + console.log('Git ignored files excluded from tests: ', gitIgnore) +} catch (error) { + // we can ignore error code 1 as this just means there are no ignored files + if (!error || typeof error !== 'object' || !('code' in error) || error.code !== 1) { + // but otherwise something bad is happening and we should re-throw + throw error + } +} + +export default defineConfig({ + plugins: [vue()], + root: resolve(import.meta.dirname), + resolve: { + preserveSymlinks: true, + }, + test: { + include: ['apps/**/*.{test,spec}.?(c|m)[jt]s?(x)'], + environment: 'jsdom', + environmentOptions: { + jsdom: { + url: 'http://nextcloud.local', + }, + }, + coverage: { + include: [ + 'apps/*/src/**', + /* 'core/src/**', */ + ], + exclude: ['**.spec.*', '**.test.*', '**.cy.*', 'core/src/tests/**'], + provider: 'v8', + reporter: ['lcov', 'text'], + }, + setupFiles: [ + resolve(import.meta.dirname, '__tests__/mock-window.js'), + resolve(import.meta.dirname, '__tests__/setup-testing-library.js'), + ], + exclude: [ + ...defaultExclude, + ...gitIgnore, + ], + globalSetup: resolve(import.meta.dirname, '__tests__/setup-global.js'), + server: { + deps: { + inline: [/@nextcloud\//], + }, + }, + }, +}) diff --git a/package.json b/package.json index d32c9e56421..6e352d30845 100644 --- a/package.json +++ b/package.json @@ -29,10 +29,10 @@ "sass:watch": "sass --watch --load-path core/css core/css/ $(for cssdir in $(find apps -mindepth 2 -maxdepth 2 -name \"css\"); do if ! $(git check-ignore -q $cssdir); then printf \"$cssdir \"; fi; done)", "stylelint": "stylelint $(for appdir in $(ls apps); do if ! $(git check-ignore -q \"apps/$appdir\"); then printf \"'apps/$appdir/**/*.{scss,vue}' \"; fi; done) 'core/**/*.{scss,vue}'", "stylelint:fix": "npm run stylelint -- --fix", - "test": "vitest run; cd build/frontend-legacy && npm run test", - "test:coverage": "vitest run --coverage --reporter=default", - "test:update-snapshots": "vitest run --update; cd build/frontend-legacy && npm run test:update-snapshots", - "test:watch": "concurrently 'vitest watch' 'cd build/frontend-legacy && npm run test:watch'", + "test": "build/demi.sh test", + "test:coverage": "build/demi.sh test:coverage", + "test:update-snapshots": "build/demi.sh test:update-snapshots", + "test:watch": "build/demi.sh --parallel test:watch", "watch": "build/demi.sh --parallel watch" }, "browserslist": [ diff --git a/vitest.config.ts b/vitest.config.ts index 663acfe3cd3..70fa4ea84ac 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,57 +3,5 @@ * SPDX-License-Identifier: CC0-1.0 */ -import vue from '@vitejs/plugin-vue' -import { exec } from 'node:child_process' -import { resolve } from 'node:path' -import { promisify } from 'node:util' -import { defaultExclude, defineConfig } from 'vitest/config' - -const gitIgnore: string[] = [] -// get all files ignored in the apps directory (e.g. if putting `view` app there). -try { - const execAsync = promisify(exec) - const { stdout } = await execAsync('git check-ignore apps/*', { cwd: __dirname }) - gitIgnore.push(...stdout.split('\n').filter(Boolean)) - // eslint-disable-next-line no-console - console.log('Git ignored files excluded from tests: ', gitIgnore) -} catch (error) { - // we can ignore error code 1 as this just means there are no ignored files - if (error.code !== 1) { - // but otherwise something bad is happening and we should re-throw - throw error - } -} - -export default defineConfig({ - plugins: [vue()], - test: { - include: ['build/frontend/apps/**/*.{test,spec}.?(c|m)[jt]s?(x)'], - environment: 'jsdom', - environmentOptions: { - jsdom: { - url: 'http://nextcloud.local', - }, - }, - coverage: { - include: ['build/frontend/apps/*/src/**', 'build/frontend/core/src/**'], - exclude: ['**.spec.*', '**.test.*', '**.cy.*', 'core/src/tests/**'], - provider: 'v8', - reporter: ['lcov', 'text'], - }, - setupFiles: [ - resolve(import.meta.dirname, '__tests__/mock-window.js'), - resolve(import.meta.dirname, '__tests__/setup-testing-library.js'), - ], - exclude: [ - ...defaultExclude, - ...gitIgnore, - ], - globalSetup: resolve(import.meta.dirname, '__tests__/setup-global.js'), - server: { - deps: { - inline: [/@nextcloud\//], - }, - }, - }, -}) +// stub - for the moment see build/frontend/vitest.config.ts +export default {}