photoprism/frontend/tests/vitest/setup.js
Ömer Duran cdf00beda4
Tests: Improve test isolation and cleanup in vitest suites (#5387)
* Tests: Improve test isolation and cleanup in vitest suites

* Tests: Add component tests for navigation, photo toolbar, and file editing

* Tests: Remove unused notification spies from batch edit component tests

* Tests: update Vitest `$notify` mock to use `vi.fn()` and include `info` method.
2025-12-30 13:03:10 +01:00

127 lines
3.3 KiB
JavaScript

import { afterEach, vi } from "vitest";
import "@testing-library/jest-dom";
import { config } from "@vue/test-utils";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
import "vuetify/styles";
import clientConfig from "./config";
import { $config } from "app/session";
import { mockGettext, mockPgettext } from "./helpers/gettext";
$config.setValues(clientConfig);
// Make config available in browser environment
window.__CONFIG__ = clientConfig;
// Create a proper Vuetify instance with all components and styles
const vuetify = createVuetify({
components,
directives,
theme: {
defaultTheme: "light",
},
});
// Polyfill ResizeObserver in jsdom environment for Vuetify components
if (typeof global.ResizeObserver === "undefined") {
global.ResizeObserver = class ResizeObserver {
constructor(callback) {
this.callback = callback;
}
observe() { }
unobserve() { }
disconnect() { }
};
}
// Configure Vue Test Utils global configuration
config.global.mocks = {
$gettext: mockGettext,
$pgettext: mockPgettext,
$isRtl: false,
$config: {
feature: () => true,
get: () => false,
getSettings: () => ({ features: { edit: true, favorites: true, download: true, archive: true } }),
allow: () => true,
featExperimental: () => false,
featDevelop: () => false,
values: {},
dir: () => "ltr",
},
$event: {
subscribe: () => "sub-id",
subscribeOnce: () => "sub-id-once",
unsubscribe: () => { },
publish: () => { },
},
$view: {
enter: () => { },
leave: () => { },
isActive: () => true,
},
$notify: { success: vi.fn(), error: vi.fn(), warn: vi.fn(), info: vi.fn() },
$fullscreen: {
isSupported: () => true,
isEnabled: () => false,
request: () => Promise.resolve(),
exit: () => Promise.resolve(),
},
$clipboard: { selection: [], has: () => false, toggle: () => { } },
$util: {
hasTouch: () => false,
encodeHTML: (s) => s,
sanitizeHtml: (s) => s,
formatSeconds: (n) => String(n),
formatRemainingSeconds: () => "0",
videoFormat: () => "avc",
videoFormatUrl: () => "/v.mp4",
thumb: () => ({ src: "/t.jpg", w: 100, h: 100 }),
},
$api: { post: vi.fn(), delete: vi.fn(), get: vi.fn() },
};
config.global.plugins = [vuetify];
config.global.stubs = {
transition: false,
};
config.global.directives = {
tooltip: {
mounted(el, binding) {
el.setAttribute("data-tooltip", binding.value);
},
},
};
const originalMount = config.global.mount;
config.global.mount = function (component, options = {}) {
options.global = options.global || {};
options.global.config = options.global.config || {};
options.global.config.globalProperties = options.global.config.globalProperties || {};
options.global.config.globalProperties.$emit = vi.fn();
// Add vuetify to all mount calls
if (!options.global.plugins) {
options.global.plugins = [vuetify];
} else if (Array.isArray(options.global.plugins)) {
options.global.plugins.push(vuetify);
}
return originalMount(component, options);
};
// Clean up after each test
afterEach(() => {
vi.resetAllMocks();
});
// Export shared configuration
export { clientConfig };
export default {
vuetify,
};