Migrate Vitest store tests from vi.mock to MSW request handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,21 +5,14 @@
|
||||
|
||||
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||
import { setActivePinia, createPinia } from "pinia";
|
||||
import { http, HttpResponse } from "msw";
|
||||
import { server } from "@/mocks/node.js";
|
||||
import { findRequest, captureRequest } from "@/mocks/request-log.js";
|
||||
|
||||
vi.mock("@/module/apiError.js", () => ({
|
||||
default: vi.fn(),
|
||||
}));
|
||||
|
||||
const { mockGet, mockPost, mockPut, mockDelete } = vi.hoisted(() => ({
|
||||
mockGet: vi.fn(),
|
||||
mockPost: vi.fn(),
|
||||
mockPut: vi.fn(),
|
||||
mockDelete: vi.fn(),
|
||||
}));
|
||||
vi.mock("@/api/client.js", () => ({
|
||||
default: { get: mockGet, post: mockPost, put: mockPut, delete: mockDelete },
|
||||
}));
|
||||
|
||||
// Mock login store to avoid its side effects
|
||||
vi.mock("@/stores/login", async () => {
|
||||
const { defineStore } = await import("pinia");
|
||||
@@ -43,7 +36,7 @@ describe("acctMgmtStore", () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia());
|
||||
store = useAcctMgmtStore();
|
||||
vi.clearAllMocks();
|
||||
document.cookie = "luciaToken=fake-test-token";
|
||||
});
|
||||
|
||||
it("has correct default state", () => {
|
||||
@@ -92,13 +85,21 @@ describe("acctMgmtStore", () => {
|
||||
|
||||
describe("createNewAccount", () => {
|
||||
it("posts to /api/users and sets flag on success", async () => {
|
||||
mockPost.mockResolvedValue({ status: 200 });
|
||||
const randomPassword = crypto.randomUUID();
|
||||
const user = { username: "newuser", password: randomPassword };
|
||||
server.use(
|
||||
http.post("/api/users", async ({ request }) => {
|
||||
const body = await request.json();
|
||||
captureRequest("POST", new URL(request.url).pathname, body);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
await store.createNewAccount(user);
|
||||
|
||||
expect(mockPost).toHaveBeenCalledWith("/api/users", user);
|
||||
const reqs = findRequest("POST", "/api/users");
|
||||
expect(reqs).toHaveLength(1);
|
||||
expect(reqs[0].body).toEqual(user);
|
||||
expect(store.isOneAccountJustCreate).toBe(true);
|
||||
expect(store.justCreateUsername).toBe("newuser");
|
||||
});
|
||||
@@ -106,26 +107,41 @@ describe("acctMgmtStore", () => {
|
||||
|
||||
describe("deleteAccount", () => {
|
||||
it("returns true on success", async () => {
|
||||
mockDelete.mockResolvedValue({ status: 200 });
|
||||
server.use(
|
||||
http.delete("/api/users/:username", ({ request }) => {
|
||||
captureRequest("DELETE", new URL(request.url).pathname);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await store.deleteAccount("alice");
|
||||
|
||||
expect(mockDelete).toHaveBeenCalledWith("/api/users/alice");
|
||||
const reqs = findRequest("DELETE", "/api/users/alice");
|
||||
expect(reqs).toHaveLength(1);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("encodes special characters in username", async () => {
|
||||
mockDelete.mockResolvedValue({ status: 200 });
|
||||
server.use(
|
||||
http.delete("/api/users/:username", ({ request }) => {
|
||||
captureRequest("DELETE", new URL(request.url).pathname);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
await store.deleteAccount("user@domain/name");
|
||||
|
||||
expect(mockDelete).toHaveBeenCalledWith(
|
||||
"/api/users/user%40domain%2Fname",
|
||||
);
|
||||
const reqs = findRequest("DELETE",
|
||||
"/api/users/user%40domain%2Fname");
|
||||
expect(reqs).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("returns false on error", async () => {
|
||||
mockDelete.mockRejectedValue(new Error("fail"));
|
||||
server.use(
|
||||
http.delete("/api/users/:username", () =>
|
||||
new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
|
||||
const result = await store.deleteAccount("alice");
|
||||
|
||||
@@ -135,7 +151,6 @@ describe("acctMgmtStore", () => {
|
||||
|
||||
describe("editAccount", () => {
|
||||
it("puts edited data", async () => {
|
||||
mockPut.mockResolvedValue({ status: 200 });
|
||||
const randomPassword = crypto.randomUUID();
|
||||
const detail = {
|
||||
username: "alice",
|
||||
@@ -143,58 +158,83 @@ describe("acctMgmtStore", () => {
|
||||
name: "Alice",
|
||||
is_active: true,
|
||||
};
|
||||
server.use(
|
||||
http.put("/api/users/:username", async ({ request }) => {
|
||||
const body = await request.json();
|
||||
captureRequest("PUT", new URL(request.url).pathname, body);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await store.editAccount("alice", detail);
|
||||
|
||||
expect(mockPut).toHaveBeenCalledWith(
|
||||
"/api/users/alice",
|
||||
expect.objectContaining({ password: randomPassword }),
|
||||
);
|
||||
const reqs = findRequest("PUT", "/api/users/alice");
|
||||
expect(reqs).toHaveLength(1);
|
||||
expect(reqs[0].body.password).toBe(randomPassword);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("addRoleToUser", () => {
|
||||
it("puts role assignment", async () => {
|
||||
mockPut.mockResolvedValue({ status: 200 });
|
||||
server.use(
|
||||
http.put("/api/users/:username/roles/:role", ({ request }) => {
|
||||
captureRequest("PUT", new URL(request.url).pathname);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await store.addRoleToUser("alice", "admin");
|
||||
|
||||
expect(mockPut).toHaveBeenCalledWith("/api/users/alice/roles/admin");
|
||||
const reqs = findRequest("PUT", "/api/users/alice/roles/admin");
|
||||
expect(reqs).toHaveLength(1);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("encodes special characters in username and role", async () => {
|
||||
mockPut.mockResolvedValue({ status: 200 });
|
||||
server.use(
|
||||
http.put("/api/users/:username/roles/:role", ({ request }) => {
|
||||
captureRequest("PUT", new URL(request.url).pathname);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
await store.addRoleToUser("user@org", "role/special");
|
||||
|
||||
expect(mockPut).toHaveBeenCalledWith(
|
||||
"/api/users/user%40org/roles/role%2Fspecial",
|
||||
);
|
||||
const reqs = findRequest("PUT",
|
||||
"/api/users/user%40org/roles/role%2Fspecial");
|
||||
expect(reqs).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("deleteRoleToUser", () => {
|
||||
it("deletes role", async () => {
|
||||
mockDelete.mockResolvedValue({ status: 200 });
|
||||
server.use(
|
||||
http.delete("/api/users/:username/roles/:role", ({ request }) => {
|
||||
captureRequest("DELETE", new URL(request.url).pathname);
|
||||
return new HttpResponse(null, { status: 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await store.deleteRoleToUser("alice", "admin");
|
||||
|
||||
expect(mockDelete).toHaveBeenCalledWith("/api/users/alice/roles/admin");
|
||||
const reqs = findRequest("DELETE",
|
||||
"/api/users/alice/roles/admin");
|
||||
expect(reqs).toHaveLength(1);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getUserDetail", () => {
|
||||
it("fetches user and sets admin flag", async () => {
|
||||
mockGet.mockResolvedValue({
|
||||
status: 200,
|
||||
data: {
|
||||
username: "alice",
|
||||
roles: [{ code: "admin" }],
|
||||
},
|
||||
});
|
||||
server.use(
|
||||
http.get("/api/users/:username", () =>
|
||||
HttpResponse.json({
|
||||
username: "alice",
|
||||
roles: [{ code: "admin" }],
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const result = await store.getUserDetail("alice");
|
||||
|
||||
@@ -203,7 +243,11 @@ describe("acctMgmtStore", () => {
|
||||
});
|
||||
|
||||
it("returns false on error", async () => {
|
||||
mockGet.mockRejectedValue(new Error("not found"));
|
||||
server.use(
|
||||
http.get("/api/users/:username", () =>
|
||||
new HttpResponse(null, { status: 500 }),
|
||||
),
|
||||
);
|
||||
|
||||
const result = await store.getUserDetail("ghost");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user