Tests: write Initial Tests for .vue Components (#5003)

* Tests: Add initial Vue component tests
* Tests: Update package scripts
This commit is contained in:
Ömer Duran 2025-05-13 11:53:17 +02:00 committed by GitHub
parent b642be2c91
commit 7ab90720ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 547 additions and 5 deletions

View file

@ -22,10 +22,12 @@
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@vitejs/plugin-react": "^4.4.1",
"@vitejs/plugin-vue": "^5.2.4",
"@vitest/coverage-v8": "^3.1.3",
"@vitest/ui": "^3.1.3",
"@vue/compiler-sfc": "^3.5.13",
"@vue/language-server": "^2.2.10",
"@vue/test-utils": "^2.4.6",
"@vvo/tzdb": "^6.161.0",
"axios": "^1.9.0",
"axios-mock-adapter": "^2.1.0",
@ -3968,6 +3970,12 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@one-ini/wasm": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
"license": "MIT"
},
"node_modules/@paralleldrive/cuid2": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
@ -4911,6 +4919,19 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
}
},
"node_modules/@vitejs/plugin-vue": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
"integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
"license": "MIT",
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"peerDependencies": {
"vite": "^5.0.0 || ^6.0.0",
"vue": "^3.2.25"
}
},
"node_modules/@vitest/coverage-v8": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.3.tgz",
@ -5377,6 +5398,16 @@
"integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==",
"license": "MIT"
},
"node_modules/@vue/test-utils": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz",
"integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==",
"license": "MIT",
"dependencies": {
"js-beautify": "^1.14.9",
"vue-component-type-helpers": "^2.0.0"
}
},
"node_modules/@vue/typescript-plugin": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/@vue/typescript-plugin/-/typescript-plugin-2.2.10.tgz",
@ -5609,6 +5640,15 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"license": "Apache-2.0"
},
"node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@ -6949,6 +6989,22 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT"
},
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"license": "MIT",
"dependencies": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
"node_modules/config-chain/node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"license": "ISC"
},
"node_modules/connect": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
@ -8165,6 +8221,69 @@
"pug": "^3.0.2"
}
},
"node_modules/editorconfig": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
"integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
"license": "MIT",
"dependencies": {
"@one-ini/wasm": "0.1.1",
"commander": "^10.0.0",
"minimatch": "9.0.1",
"semver": "^7.5.3"
},
"bin": {
"editorconfig": "bin/editorconfig"
},
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/editorconfig/node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/minimatch": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/editorconfig/node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -11478,6 +11597,80 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/js-beautify": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
"integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
"license": "MIT",
"dependencies": {
"config-chain": "^1.1.13",
"editorconfig": "^1.0.4",
"glob": "^10.4.2",
"js-cookie": "^3.0.5",
"nopt": "^7.2.1"
},
"bin": {
"css-beautify": "js/bin/css-beautify.js",
"html-beautify": "js/bin/html-beautify.js",
"js-beautify": "js/bin/js-beautify.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/js-beautify/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/js-beautify/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-beautify/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/js-stringify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
@ -12822,6 +13015,21 @@
"node": ">=6.14.4"
}
},
"node_modules/nopt": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"license": "ISC",
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -15165,6 +15373,12 @@
"asap": "~2.0.3"
}
},
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"license": "ISC"
},
"node_modules/protocol-buffers-schema": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
@ -19026,6 +19240,12 @@
"sanitize-html": "^2.0.0"
}
},
"node_modules/vue-component-type-helpers": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.10.tgz",
"integrity": "sha512-iDUO7uQK+Sab2tYuiP9D1oLujCWlhHELHMgV/cB13cuGbG4qwkLHvtfWb6FzvxrIOPDnU0oHsz2MlQjhYDeaHA==",
"license": "MIT"
},
"node_modules/vue-eslint-parser": {
"version": "10.1.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz",

View file

@ -21,6 +21,7 @@
"test:vitest": "vitest run",
"test:vitest:watch": "vitest",
"test:vitest:coverage": "vitest run --coverage",
"test:vitest:component": "vitest run tests/vitest/component",
"test:vitest:ui": "vitest --ui",
"testcafe": "testcafe",
"trace": "webpack --stats-children",
@ -137,11 +138,13 @@
"webpack-manifest-plugin": "^5.0.1",
"webpack-md5-hash": "^0.0.6",
"webpack-merge": "^6.0.1",
"webpack-plugin-vuetify": "^3.1.1"
"webpack-plugin-vuetify": "^3.1.1",
"@vitejs/plugin-vue": "^5.2.4",
"@vue/test-utils": "^2.4.6"
},
"engines": {
"node": ">= 18.0.0",
"npm": ">= 9.0.0",
"yarn": "please use npm"
}
}
}

View file

@ -0,0 +1,105 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { mount } from "@vue/test-utils";
import PLoadingBar from "component/loading-bar.vue";
// Mock $event subscription
const mockSubscribe = vi.fn();
// Mock queue function to execute callbacks immediately
vi.mock("component/loading-bar.vue", async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
queue: (fn) => {
fn((next) => {
if (next) next();
});
},
};
});
describe("PLoadingBar component", () => {
let wrapper;
beforeEach(() => {
vi.clearAllMocks();
vi.useFakeTimers();
wrapper = mount(PLoadingBar, {
global: {
mocks: {
$event: {
subscribe: mockSubscribe,
},
},
stubs: {
transition: false,
},
},
});
});
afterEach(() => {
vi.useRealTimers();
});
it("should render correctly", () => {
expect(wrapper.vm).toBeTruthy();
expect(wrapper.find("#p-loading-bar").exists()).toBe(true);
expect(wrapper.find(".top-progress").exists()).toBe(false); // Initially not visible
// Check computed properties
expect(wrapper.vm.progressColor).toBe("#29d"); // Default color
expect(wrapper.vm.isStarted).toBe(false);
});
it("should subscribe to ajax events on mount", () => {
expect(mockSubscribe).toHaveBeenCalledTimes(2);
expect(mockSubscribe.mock.calls[0][0]).toBe("ajax.start");
expect(mockSubscribe.mock.calls[1][0]).toBe("ajax.end");
});
it("should start the loading bar", async () => {
wrapper.vm.start();
await wrapper.vm.$nextTick();
expect(wrapper.vm.visible).toBe(true);
// After transition, the bar should be displayed
wrapper.vm.afterEnter();
expect(wrapper.vm.status).not.toBeNull();
});
it("should make progress visible when started", async () => {
expect(wrapper.vm.visible).toBe(false);
// Start the bar
wrapper.vm.start();
await wrapper.vm.$nextTick();
// Should be visible now
expect(wrapper.vm.visible).toBe(true);
});
it("should handle error state", async () => {
wrapper.vm.fail();
await wrapper.vm.$nextTick();
expect(wrapper.vm.error).toBe(true);
expect(wrapper.vm.progressColor).toBe("#f44336"); // Error color
});
it("should pause the loading bar", () => {
wrapper.vm.start();
wrapper.vm.pause();
expect(wrapper.vm.isPaused).toBe(true);
});
it("should initialize progress to zero", () => {
expect(wrapper.vm.progress).toBe(0);
expect(wrapper.vm.getProgress()).toBe(0);
});
});

View file

@ -0,0 +1,16 @@
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import PLoading from "component/loading.vue";
describe("PLoading component", () => {
it("should render correctly", () => {
const wrapper = mount(PLoading);
// Check if component renders
expect(wrapper.vm).toBeTruthy();
// Check if the progress circular element exists
const progressCircular = wrapper.find(".vprogresscircular-stub");
expect(progressCircular.exists()).toBe(true);
});
});

View file

@ -0,0 +1,125 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { mount } from "@vue/test-utils";
import PSidebarInfo from "component/sidebar/info.vue";
import { DateTime } from "luxon";
// Mock dependencies
vi.mock("component/map.vue", () => ({
default: {
name: "p-map",
template: "<div class='p-map-stub'></div>",
props: ["lat", "lng"],
},
}));
vi.mock("options/formats", () => ({
DATETIME_MED: "DATETIME_MED",
DATETIME_MED_TZ: "DATETIME_MED_TZ",
}));
describe("PSidebarInfo component", () => {
let wrapper;
const mockModel = {
UID: "abc123",
Title: "Test Title",
Caption: "Test Caption",
TakenAtLocal: "2023-01-01T10:00:00Z",
TimeZone: "UTC",
Lat: 52.52,
Lng: 13.405,
getTypeInfo: vi.fn().mockReturnValue("JPEG, 1920x1080"),
getTypeIcon: vi.fn().mockReturnValue("mdi-file-image"),
getLatLng: vi.fn().mockReturnValue("52.5200, 13.4050"),
copyLatLng: vi.fn(),
};
beforeEach(() => {
vi.clearAllMocks();
wrapper = mount(PSidebarInfo, {
props: {
modelValue: mockModel,
context: "photos",
},
global: {
stubs: {
PMap: true,
},
},
});
});
it("should render correctly with model data", () => {
expect(wrapper.vm).toBeTruthy();
expect(wrapper.find(".p-sidebar-info").exists()).toBe(true);
const html = wrapper.html();
expect(html).toContain("Test Title");
expect(html).toContain("Test Caption");
expect(mockModel.getTypeInfo).toHaveBeenCalled();
expect(mockModel.getTypeIcon).toHaveBeenCalled();
expect(mockModel.getLatLng).toHaveBeenCalled();
});
it("should emit close event when close button is clicked", async () => {
const closeButton = wrapper.find(".vbtn-stub");
await closeButton.trigger("click");
expect(wrapper.emitted()).toHaveProperty("close");
});
it("should trigger copyLatLng when location is clicked", async () => {
// Find the location item by its class
const clickableItems = wrapper.findAll(".clickable");
if (clickableItems.length > 0) {
await clickableItems[0].trigger("click");
expect(mockModel.copyLatLng).toHaveBeenCalled();
}
});
it("should format time correctly", () => {
// Mock DateTime.fromISO to return a controllable object
const mockToLocaleString = vi.fn().mockReturnValue("January 1, 2023, 10:00 AM");
DateTime.fromISO = vi.fn().mockReturnValue({
toLocaleString: mockToLocaleString,
});
const formattedTime = wrapper.vm.formatTime(mockModel);
expect(DateTime.fromISO).toHaveBeenCalledWith("2023-01-01T10:00:00Z", { zone: "UTC" });
expect(mockToLocaleString).toHaveBeenCalledWith("DATETIME_MED_TZ");
expect(formattedTime).toBe("January 1, 2023, 10:00 AM");
});
it("should handle model with timezone", () => {
// Create a model with non-UTC timezone
const modelWithTZ = {
...mockModel,
TimeZone: "Europe/Berlin",
};
// Mock DateTime.fromISO to return a controllable object
const mockToLocaleString = vi.fn().mockReturnValue("January 1, 2023, 11:00 AM CET");
DateTime.fromISO = vi.fn().mockReturnValue({
toLocaleString: mockToLocaleString,
});
const formattedTime = wrapper.vm.formatTime(modelWithTZ);
expect(DateTime.fromISO).toHaveBeenCalledWith("2023-01-01T10:00:00Z", { zone: "Europe/Berlin" });
expect(mockToLocaleString).toHaveBeenCalledWith("DATETIME_MED_TZ");
expect(formattedTime).toBe("January 1, 2023, 11:00 AM CET");
});
it("should handle model without taken time", () => {
const modelWithoutTime = {
...mockModel,
TakenAtLocal: null,
};
const formattedTime = wrapper.vm.formatTime(modelWithoutTime);
expect(formattedTime).toBe("Unknown");
});
});

View file

@ -0,0 +1,72 @@
import { config } from "@vue/test-utils";
import { vi } from "vitest";
// Mock Vuetify components
const vuetifyComponents = [
"VBtn",
"VToolbar",
"VToolbarTitle",
"VList",
"VListItem",
"VDivider",
"VProgressCircular",
"VIcon",
"VRow",
"VCol",
"VCard",
"VCardTitle",
"VCardText",
"VCardActions",
"VTextField",
"VTextarea",
"VSheet",
];
// Create stubs for Vuetify components
const vuetifyStubs = vuetifyComponents.reduce((acc, component) => {
acc[component] = {
name: component.toLowerCase(),
template: `<div data-testid="${component.toLowerCase()}" class="${component.toLowerCase()}-stub"><slot></slot></div>`,
};
acc[component.toLowerCase()] = {
name: component.toLowerCase(),
template: `<div data-testid="${component.toLowerCase()}" class="${component.toLowerCase()}-stub"><slot></slot></div>`,
};
return acc;
}, {});
// Configure Vue Test Utils global configuration
config.global.mocks = {
$gettext: (text) => text,
$isRtl: false,
$config: {
feature: (_name) => true,
},
};
config.global.stubs = {
...vuetifyStubs,
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();
return originalMount(component, options);
};
export default {
vuetifyStubs,
};

View file

@ -1,18 +1,19 @@
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
import vue from "@vitejs/plugin-vue";
import tsconfigPaths from "vite-tsconfig-paths";
import path from "path";
export default defineConfig({
plugins: [react(), tsconfigPaths()],
plugins: [react(), vue(), tsconfigPaths()],
test: {
globals: true,
environment: "jsdom",
setupFiles: "./tests/vitest/setup.js",
setupFiles: ["./tests/vitest/setup.js", "./tests/vitest/vue-setup.js"],
include: ["tests/vitest/**/*.{test,spec}.{js,jsx}"],
coverage: {
reporter: ["text", "html"],
include: ["src/**/*.{js,jsx}"],
include: ["src/**/*.{js,jsx,vue}"],
exclude: ["src/locales/**"],
},
alias: {