test(ui): i corrected UI Testing

This commit is contained in:
2026-04-08 01:45:12 +00:00
parent 5d378ccb56
commit 546bf65b8b
10 changed files with 84 additions and 41 deletions
View File
+9
View File
@@ -0,0 +1,9 @@
import { expect, test } from "bun:test";
// UI unit tests use Vitest, not Bun's native test runner.
// Run them with: bun run test:unit -- --run
//
// This placeholder ensures `bun test` exits 0 rather than failing with "No tests found".
test("UI tests use Vitest - run with: bun run test:unit -- --run", () => {
expect(true).toBe(true);
});
+12
View File
@@ -0,0 +1,12 @@
# The UI project uses Vitest (via `bun run test:unit`) for unit tests, not Bun's native test runner.
# Bun's runner lacks support for vi.hoisted, SvelteKit virtual modules ($env, $app), and jsdom.
#
# To run tests:
# Unit tests: bun run test:unit -- --run
# E2E tests: bun run test:e2e
# All tests: bun run test
#
# This configuration points Bun's test discovery at an isolated directory so that
# `bun test` does not erroneously pick up Vitest-formatted spec files.
[test]
root = ".bun-tests"
@@ -10,7 +10,7 @@ const { mockApi } = vi.hoisted(() => ({
},
}));
vi.mock("../axios", () => ({
vi.mock("$lib/optima-api/axios", () => ({
default: mockApi,
api: mockApi,
}));
+1 -1
View File
@@ -6,7 +6,7 @@ const { mockApi } = vi.hoisted(() => ({
},
}));
vi.mock("../axios", () => ({
vi.mock("$lib/optima-api/axios", () => ({
default: mockApi,
api: mockApi,
}));
+29 -37
View File
@@ -1,9 +1,8 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const { mockRedirect, mockAxiosPost, mockIo, mockApi } = vi.hoisted(() => ({
const { mockRedirect, mockAxiosPost, mockApi } = vi.hoisted(() => ({
mockRedirect: vi.fn(),
mockAxiosPost: vi.fn(),
mockIo: vi.fn(),
mockApi: {
get: vi.fn(),
post: vi.fn(),
@@ -27,13 +26,13 @@ vi.mock("axios", () => ({
post: mockAxiosPost,
}));
vi.mock("../axios", () => ({
vi.mock("$lib/optima-api/axios", () => ({
default: mockApi,
api: mockApi,
}));
vi.mock("socket.io-client", () => ({
io: mockIo,
io: vi.fn(),
}));
import { user } from "./user";
@@ -128,45 +127,38 @@ describe("user module", () => {
expect(result).toBe(fakeRedirect);
});
it("awaitAuthCallback resolves when socket event delivers tokens", async () => {
const handlers: Record<string, (payload?: any) => void> = {};
const disconnect = vi.fn();
it("awaitAuthCallback resolves when polling returns 200 with tokens", async () => {
const mockFetch = vi
.fn()
.mockResolvedValueOnce({
status: 202,
})
.mockResolvedValueOnce({
status: 200,
json: vi.fn().mockResolvedValue({
data: { accessToken: "access", refreshToken: "refresh" },
}),
});
vi.stubGlobal("fetch", mockFetch);
mockIo.mockReturnValueOnce({
on: vi.fn((event: string, callback: (payload?: any) => void) => {
handlers[event] = callback;
}),
disconnect,
});
const result = await user.awaitAuthCallback("cb-key");
const promise = user.awaitAuthCallback("cb-key");
expect(result).toEqual({ accessToken: "access", refreshToken: "refresh" });
expect(mockFetch).toHaveBeenCalledWith(
"https://api.example.com/v1/auth/callback/cb-key"
);
handlers["auth:login:callback:cb-key"]?.({
accessToken: "access",
refreshToken: "refresh",
});
await expect(promise).resolves.toEqual({
accessToken: "access",
refreshToken: "refresh",
});
expect(disconnect).toHaveBeenCalled();
vi.unstubAllGlobals();
});
it("awaitAuthCallback rejects on connect_error", async () => {
const handlers: Record<string, (payload?: any) => void> = {};
it("awaitAuthCallback rejects when polling returns unexpected status", async () => {
const mockFetch = vi.fn().mockResolvedValue({ status: 500 });
vi.stubGlobal("fetch", mockFetch);
mockIo.mockReturnValueOnce({
on: vi.fn((event: string, callback: (payload?: any) => void) => {
handlers[event] = callback;
}),
disconnect: vi.fn(),
});
await expect(user.awaitAuthCallback("cb-key")).rejects.toThrow(
"Unexpected status 500"
);
const promise = user.awaitAuthCallback("cb-key");
handlers.connect_error?.(new Error("socket failed"));
await expect(promise).rejects.toThrow("socket failed");
vi.unstubAllGlobals();
});
});
@@ -1,6 +1,5 @@
import { Actions, redirect } from "@sveltejs/kit";
import { optima } from "$lib";
import { INTERNAL_API_URL } from "$env/static/private";
export const actions: Actions = {
login: async (event) => {
@@ -8,7 +7,6 @@ export const actions: Actions = {
const tokens = await optima.user.awaitAuthCallback(
data.get("callbackKey") as string,
INTERNAL_API_URL,
);
event.cookies.set("accessToken", tokens.accessToken, {
@@ -90,6 +90,7 @@ describe("admin/users +page.server.ts", () => {
return {
get: (key: string) => entries[key] ?? null,
getAll: (key: string) => (entries[key] ? [entries[key]] : []),
has: (key: string) => key in entries,
};
}
@@ -6,6 +6,7 @@ const { mockOptima, mockCheckPermissions, mockHandleApiError } = vi.hoisted(
sales: {
fetchOne: vi.fn(),
fetchWorkflowStatus: vi.fn(),
fetchOpportunityTypes: vi.fn(),
},
},
mockCheckPermissions: vi.fn(),
@@ -34,6 +35,7 @@ describe("sales/opportunity/[id] +page.server.ts load", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.spyOn(console, "error").mockImplementation(() => {});
mockOptima.sales.fetchOpportunityTypes.mockResolvedValue({ data: [] });
});
it("returns empty data when no token", async () => {