已發布·持續改進
Vue.js · Nuxt 指南 · 5/6
本章目前僅提供英文版。
Tests in a Vue project usually come in three layers. Pure logic such as composables and stores is checked with Vitest, components with Vitest plus Vue Test Utils, and real user flows with an end-to-end tool such as Playwright. In Nuxt projects, @nuxt/test-utils boots a Nuxt environment inside your tests.
If you selected Vitest in create-vue, everything is already configured. To add it by hand, install these packages:
npm install -D vitest @vue/test-utils jsdomvitest.config.ts extends the Vite config and selects the jsdom environment, which emulates browser APIs:
import { fileURLToPath } from "node:url";
import { mergeConfig, defineConfig, configDefaults } from "vitest/config";
import viteConfig from "./vite.config";
export default mergeConfig(
viteConfig,
defineConfig({
test: {
environment: "jsdom",
exclude: [...configDefaults.exclude, "e2e/**"],
root: fileURLToPath(new URL("./", import.meta.url)),
},
}),
);npm run test:unit (or npx vitest) runs tests in watch mode, re-running only the affected tests each time you save.
Call a composable like any function and assert on the result. For Pinia stores, activate a fresh Pinia before each test so tests do not leak state into each other.
import { describe, it, expect, beforeEach } from "vitest";
import { setActivePinia, createPinia } from "pinia";
import { useCounter } from "@/composables/useCounter";
import { useCartStore } from "@/stores/cart";
describe("useCounter", () => {
it("increments and doubles", () => {
const { count, double, increment } = useCounter(1);
increment();
expect(count.value).toBe(2);
expect(double.value).toBe(4);
});
});
describe("cart store", () => {
beforeEach(() => setActivePinia(createPinia()));
it("increases quantity for the same item", () => {
const cart = useCartStore();
cart.add({ id: 1, name: "Book", price: 100 });
cart.add({ id: 1, name: "Book", price: 100 });
expect(cart.items[0].qty).toBe(2);
expect(cart.total).toBe(200);
});
});mount from Vue Test Utils renders a component and returns a wrapper. Pass props, find elements, trigger events, then assert on the rendered text or emitted events. DOM updates are asynchronous, so await calls to trigger and setValue.
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import TodoItem from "@/components/TodoItem.vue";
describe("TodoItem", () => {
it("renders the text and emits remove", async () => {
const wrapper = mount(TodoItem, { props: { text: "Groceries", done: false } });
expect(wrapper.text()).toContain("Groceries");
await wrapper.find("button").trigger("click");
expect(wrapper.emitted("remove")?.[0]).toEqual(["user"]);
});
});Components that rely on global plugins can receive them with mount(Comp, { global: { plugins: [router, createPinia()] } }). Tests that assert on what the user sees, rather than on implementation details, survive refactoring much better.
Nuxt components depend on auto-imports and Nuxt composables, so they will not run in a plain jsdom environment. @nuxt/test-utils provides a nuxt environment that boots the Nuxt runtime inside tests, plus mountSuspended.
npm install -D @nuxt/test-utils vitest @vue/test-utils happy-dom// vitest.config.ts
import { defineVitestConfig } from "@nuxt/test-utils/config";
export default defineVitestConfig({
test: { environment: "nuxt" },
});// tests/counter.nuxt.test.ts
import { it, expect } from "vitest";
import { mountSuspended } from "@nuxt/test-utils/runtime";
import AppCounter from "~/components/AppCounter.vue";
it("renders inside the Nuxt environment", async () => {
const wrapper = await mountSuspended(AppCounter);
expect(wrapper.text()).toContain("0");
});mountSuspended waits for async setup and useFetch to resolve before returning. You can mock server API calls with registerEndpoint.
End-to-end tests open the app in a real browser and drive it like a user would. Select Playwright in create-vue, or add it with npm init playwright@latest.
// e2e/home.spec.ts
import { test, expect } from "@playwright/test";
test("filters the list by search query", async ({ page }) => {
await page.goto("/");
await page.getByPlaceholder("Search").fill("Vue");
await expect(page.getByRole("listitem")).toHaveCount(1);
});Set the webServer option in playwright.config.ts to the command that starts your dev or preview server, and Playwright launches it before the tests. Run npx playwright test, and add --ui to step through tests interactively.
setActivePinia(createPinia()) before each test.nuxt environment and mountSuspended from @nuxt/test-utils.
0 則留言
登入 · 登入後即可留言。
來留下第一則留言吧。