WFDASH-WEBAPP/src/lib/server/pocketbase-admin.test.ts
SJCoetz 12fa65a481 feat: add new order, invoice, and dashboard management tools
- Add server-side `/api/v1/dashboard` endpoint to reduce client-side payload and round trips
- Implement invoice upload and order-item SKU update APIs with complete test suites
- Refactor order and order-items list endpoints (including MCP tools) to support proper PocketBase filter and sort params
- Fix pagination validation for order-items route to clamp page ≥1 and perPage 1-500
- Add redirects in next.config.ts to map underscore collection paths to hyphenated API routes
- Improve buyer tasks page to avoid redundant tab count refetches when switching tabs
- Refactor collection confirm components with editable SKUs and updated accessibility labels
- Add cached admin PocketBase auth to minimize repeated authentication calls
- Add performance testing scripts for dashboard endpoint latency
- Update quotes list route to default to excluding archived counts
- Fix photo strip component text and labels for non-invoice documents
- Refactor sprint page to lazy load supplier/customer data for pricing modal
- Clean up unused imports in test files
- Add full test coverage for all new APIs, services, and components
2026-08-05 23:00:54 +02:00

72 lines
2.4 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
// Mock the pocketbase module so getAdminPocketBase doesn't try to open a socket.
const authWithPassword = vi.fn().mockResolvedValue({
token: "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjQ3NDYwODk2MDB9.sig",
});
const authStoreSave = vi.fn();
vi.mock("pocketbase", () => {
// Must be a class (or function) because the production code does `new PocketBase(url)`.
const FakePocketBase = vi.fn().mockImplementation(function () {
return {
authStore: {
save: authStoreSave,
record: { id: "admin-1" },
},
collection: () => ({
authWithPassword,
}),
};
});
return { default: FakePocketBase };
});
import { clearAdminPocketBaseAuthCache, getAdminPocketBase } from "./pocketbase-admin";
describe("getAdminPocketBase", () => {
const ORIGINAL_EMAIL = process.env.PB_ADMIN_EMAIL;
const ORIGINAL_PASSWORD = process.env.PB_ADMIN_PASSWORD;
beforeEach(() => {
process.env.PB_ADMIN_EMAIL = "admin@example.com";
process.env.PB_ADMIN_PASSWORD = "secret";
clearAdminPocketBaseAuthCache();
authWithPassword.mockClear();
authStoreSave.mockClear();
});
afterEach(() => {
clearAdminPocketBaseAuthCache();
if (ORIGINAL_EMAIL === undefined) delete process.env.PB_ADMIN_EMAIL;
else process.env.PB_ADMIN_EMAIL = ORIGINAL_EMAIL;
if (ORIGINAL_PASSWORD === undefined) delete process.env.PB_ADMIN_PASSWORD;
else process.env.PB_ADMIN_PASSWORD = ORIGINAL_PASSWORD;
});
it("returns a PocketBase instance and authenticates with the admin credentials", async () => {
const pb = await getAdminPocketBase();
expect(pb).toBeDefined();
expect(authWithPassword).toHaveBeenCalledWith("admin@example.com", "secret");
});
it("reuses the cached admin token on the second call", async () => {
await getAdminPocketBase();
authWithPassword.mockClear();
const pb = await getAdminPocketBase();
expect(pb).toBeDefined();
expect(authWithPassword).not.toHaveBeenCalled();
expect(authStoreSave).toHaveBeenCalledWith(
"eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjQ3NDYwODk2MDB9.sig",
);
});
it("throws a clear error when admin env vars are missing", async () => {
delete process.env.PB_ADMIN_EMAIL;
delete process.env.PB_ADMIN_PASSWORD;
await expect(getAdminPocketBase()).rejects.toThrow(
/PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD are required/
);
});
});