Files
pleno-vue/tests/unit/authenticated-request.spec.js
T

167 lines
4.4 KiB
JavaScript

// @vitest-environment jsdom
import { beforeEach, describe, expect, it, vi } from "vitest";
const { axiosMock } = vi.hoisted(() => ({
axiosMock: vi.fn(),
}));
vi.mock("axios", () => ({
default: axiosMock,
}));
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
import {
__configureRequestQueueForTests,
__resetRequestQueueForTests,
requestQueueState,
} from "@/services/requestQueue.js";
const flushMicrotasks = async () => {
await Promise.resolve();
await Promise.resolve();
};
const flushManyMicrotasks = async (rounds = 10) => {
for (let index = 0; index < rounds; index += 1) {
await Promise.resolve();
}
};
const createDeferred = () => {
let resolve;
let reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
};
describe("authenticatedRequest", () => {
beforeEach(() => {
axiosMock.mockReset();
__resetRequestQueueForTests();
__configureRequestQueueForTests({
maxConcurrentGet: 1,
maxConcurrentOther: 1,
spacingMs: 0,
retryByStatusCode: {},
});
localStorage.clear();
localStorage.setItem("token", "token");
});
it("suppresses known scanner lpr extraction failures and resolves with response", async () => {
const response = {
status: 500,
data: {
success: false,
data: {
message: "Internal server error: License plate extraction failed.",
},
meta: [],
includes: [],
},
};
axiosMock.mockRejectedValueOnce({ response });
const catchCallable = vi.fn();
const result = await authenticatedRequest("/modules/scanner/lpr", "POST", { base64_image: "x" }, catchCallable);
expect(result).toBe(response);
expect(catchCallable).not.toHaveBeenCalled();
});
it("continues to reject non-suppressed scanner errors", async () => {
const error = {
response: {
status: 500,
data: {
success: false,
data: {
message: "Internal server error: Different scanner problem.",
},
},
},
};
axiosMock.mockRejectedValueOnce(error);
const catchCallable = vi.fn();
await expect(
authenticatedRequest("/modules/scanner/lpr", "POST", { base64_image: "x" }, catchCallable)
).rejects.toBe(error);
expect(catchCallable).toHaveBeenCalledWith(error);
});
it("continues to reject non-lpr errors", async () => {
const error = {
response: {
status: 500,
data: {
success: false,
data: {
message: "Internal server error: License plate extraction failed.",
},
},
},
};
axiosMock.mockRejectedValueOnce(error);
await expect(authenticatedRequest("/auth/session", "GET")).rejects.toBe(error);
});
it("queues requests and executes them sequentially", async () => {
const first = createDeferred();
const second = createDeferred();
const third = createDeferred();
const deferredCalls = [first, second, third];
axiosMock.mockImplementation(() => deferredCalls.shift()?.promise);
const request1 = authenticatedRequest("/one", "GET");
const request2 = authenticatedRequest("/two", "GET");
const request3 = authenticatedRequest("/three", "GET");
await flushMicrotasks();
expect(axiosMock).toHaveBeenCalledTimes(1);
expect(requestQueueState.active).toBe(1);
expect(requestQueueState.pending).toBe(2);
expect(requestQueueState.batchTotal).toBe(3);
first.resolve({ status: 200, data: { id: 1 } });
await flushManyMicrotasks();
expect(axiosMock).toHaveBeenCalledTimes(2);
expect(requestQueueState.active).toBe(1);
expect(requestQueueState.pending).toBe(1);
second.resolve({ status: 200, data: { id: 2 } });
await flushManyMicrotasks();
expect(axiosMock).toHaveBeenCalledTimes(3);
expect(requestQueueState.active).toBe(1);
expect(requestQueueState.pending).toBe(0);
third.resolve({ status: 200, data: { id: 3 } });
await expect(Promise.all([request1, request2, request3])).resolves.toEqual([
{ status: 200, data: { id: 1 } },
{ status: 200, data: { id: 2 } },
{ status: 200, data: { id: 3 } },
]);
await flushMicrotasks();
expect(requestQueueState.active).toBe(0);
expect(requestQueueState.pending).toBe(0);
expect(requestQueueState.batchCompleted).toBe(3);
expect(requestQueueState.batchFailed).toBe(0);
});
});