From 337386caa8e1c0004dc7530137b246b0272d63ac Mon Sep 17 00:00:00 2001 From: Nikolay Tatarinov Date: Wed, 4 Mar 2026 14:12:48 +0300 Subject: [PATCH] Enhance Vitest configuration and improve Vue integration - Added Vue plugin to vitest.config.ts for better component testing. - Introduced vitest.setup.ts to expose Vue reactivity and lifecycle methods globally, ensuring compatibility with .vue components. - Updated mock implementations in nuxt-imports.ts to include readonly for improved reactivity handling. - Refactored useMapBookmarks and useToast composables to utilize readonly from Vue for better state management. --- frontend-nuxt/__mocks__/nuxt-imports.ts | 24 +++++++++++++++-- frontend-nuxt/composables/useMapBookmarks.ts | 2 ++ frontend-nuxt/composables/useToast.ts | 2 ++ frontend-nuxt/lib/__tests__/Character.test.ts | 23 ++++++++++------ frontend-nuxt/lib/__tests__/Marker.test.ts | 9 +++---- frontend-nuxt/vitest.config.ts | 3 +++ frontend-nuxt/vitest.setup.ts | 27 +++++++++++++++++++ 7 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 frontend-nuxt/vitest.setup.ts diff --git a/frontend-nuxt/__mocks__/nuxt-imports.ts b/frontend-nuxt/__mocks__/nuxt-imports.ts index 44435a3..6a766f6 100644 --- a/frontend-nuxt/__mocks__/nuxt-imports.ts +++ b/frontend-nuxt/__mocks__/nuxt-imports.ts @@ -1,6 +1,26 @@ -import { ref, reactive, computed, watch, watchEffect, onMounted, onUnmounted, nextTick } from 'vue' +import { + ref, + reactive, + computed, + watch, + watchEffect, + onMounted, + onUnmounted, + nextTick, + readonly, +} from 'vue' -export { ref, reactive, computed, watch, watchEffect, onMounted, onUnmounted, nextTick } +export { + ref, + reactive, + computed, + watch, + watchEffect, + onMounted, + onUnmounted, + nextTick, + readonly, +} export function useRuntimeConfig() { return { diff --git a/frontend-nuxt/composables/useMapBookmarks.ts b/frontend-nuxt/composables/useMapBookmarks.ts index f932fe5..67eb896 100644 --- a/frontend-nuxt/composables/useMapBookmarks.ts +++ b/frontend-nuxt/composables/useMapBookmarks.ts @@ -1,3 +1,5 @@ +import { readonly } from 'vue' + export interface MapBookmark { id: string name: string diff --git a/frontend-nuxt/composables/useToast.ts b/frontend-nuxt/composables/useToast.ts index 5da66bb..b59f496 100644 --- a/frontend-nuxt/composables/useToast.ts +++ b/frontend-nuxt/composables/useToast.ts @@ -1,3 +1,5 @@ +import { readonly } from 'vue' + export type ToastType = 'success' | 'error' | 'info' export interface Toast { diff --git a/frontend-nuxt/lib/__tests__/Character.test.ts b/frontend-nuxt/lib/__tests__/Character.test.ts index 130468e..01d45f2 100644 --- a/frontend-nuxt/lib/__tests__/Character.test.ts +++ b/frontend-nuxt/lib/__tests__/Character.test.ts @@ -4,29 +4,36 @@ import type L from 'leaflet' import type { Map, LayerGroup } from 'leaflet' import { createCharacter, type CharacterData, type CharacterMapViewRef } from '../Character' -vi.mock('leaflet', () => { +const { leafletMock } = vi.hoisted(() => { const markerMock = { on: vi.fn().mockReturnThis(), addTo: vi.fn().mockReturnThis(), setLatLng: vi.fn().mockReturnThis(), setIcon: vi.fn().mockReturnThis(), } - return { - default: { - marker: vi.fn(() => markerMock), - Icon: vi.fn().mockImplementation(() => ({})), - }, + const Icon = vi.fn().mockImplementation(function (this: unknown) { + return {} + }) + const L = { marker: vi.fn(() => markerMock), - Icon: vi.fn().mockImplementation(() => ({})), + Icon, } + return { leafletMock: L } }) +vi.mock('leaflet', () => ({ + __esModule: true, + default: leafletMock, + marker: leafletMock.marker, + Icon: leafletMock.Icon, +})) + vi.mock('~/lib/LeafletCustomTypes', () => ({ HnHMaxZoom: 6, })) function getL(): L { - return require('leaflet').default + return leafletMock as unknown as L } function makeCharData(overrides: Partial = {}): CharacterData { diff --git a/frontend-nuxt/lib/__tests__/Marker.test.ts b/frontend-nuxt/lib/__tests__/Marker.test.ts index 3612fcb..ca03def 100644 --- a/frontend-nuxt/lib/__tests__/Marker.test.ts +++ b/frontend-nuxt/lib/__tests__/Marker.test.ts @@ -15,14 +15,13 @@ vi.mock('leaflet', () => { openPopup: vi.fn().mockReturnThis(), closePopup: vi.fn().mockReturnThis(), } - return { - default: { - marker: vi.fn(() => markerMock), - Icon: vi.fn(), - }, + const point = (x: number, y: number) => ({ x, y }) + const L = { marker: vi.fn(() => markerMock), Icon: vi.fn(), + point, } + return { __esModule: true, default: L, ...L } }) vi.mock('~/lib/LeafletCustomTypes', () => ({ diff --git a/frontend-nuxt/vitest.config.ts b/frontend-nuxt/vitest.config.ts index 4b03f30..5a6b40a 100644 --- a/frontend-nuxt/vitest.config.ts +++ b/frontend-nuxt/vitest.config.ts @@ -1,11 +1,14 @@ import { defineConfig } from 'vitest/config' +import Vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ + plugins: [Vue()], test: { environment: 'happy-dom', include: ['**/__tests__/**/*.test.ts', '**/*.test.ts'], globals: true, + setupFiles: ['./vitest.setup.ts'], coverage: { provider: 'v8', reporter: ['text', 'html'], diff --git a/frontend-nuxt/vitest.setup.ts b/frontend-nuxt/vitest.setup.ts new file mode 100644 index 0000000..fc63e3a --- /dev/null +++ b/frontend-nuxt/vitest.setup.ts @@ -0,0 +1,27 @@ +/** + * Expose Vue reactivity and lifecycle on globalThis so that .vue components + * that rely on Nuxt auto-imports (ref, computed, etc.) work in Vitest. + */ +import { + ref, + computed, + reactive, + watch, + watchEffect, + onMounted, + onUnmounted, + nextTick, + readonly, +} from 'vue' + +Object.assign(globalThis, { + ref, + computed, + reactive, + watch, + watchEffect, + onMounted, + onUnmounted, + nextTick, + readonly, +})