import { createHttpMockingServer } from "@hyper-fetch/testing"; import { interceptorCallback } from "../../utils"; import { testCallbacksExecution } from "../../shared"; import { Client } from "client"; import { xhrExtra } from "http-adapter"; const { resetMocks, startServer, stopServer, mockRequest } = createHttpMockingServer(); describe("Client [ Interceptor ]", () => { let client = new Client({ url: "shared-base-url/" }); let request = client.createRequest<{ response: any }>()({ endpoint: "shared-base-endpoint" }); const spy1 = vi.fn(); const spy2 = vi.fn(); const spy3 = vi.fn(); beforeAll(() => { startServer(); }); beforeEach(() => { client = new Client({ url: "shared-base-url/" }); request = client.createRequest<{ response: any }>()({ endpoint: "shared-base-endpoint" }); resetMocks(); vi.clearAllMocks(); }); afterAll(() => { stopServer(); }); describe("When interceptor callbacks being added", () => { it("should assign onError interceptors", async () => { const callback = interceptorCallback(); client.onError(callback).onError(callback); expect(client.unstable_onErrorCallbacks).toHaveLength(2); expect(client.unstable_onErrorCallbacks[0]).toEqual(callback); expect(client.unstable_onErrorCallbacks[1]).toEqual(callback); }); it("should assign onSuccess interceptors", async () => { const callback = interceptorCallback(); client.onSuccess(callback).onSuccess(callback); expect(client.unstable_onSuccessCallbacks).toHaveLength(2); expect(client.unstable_onSuccessCallbacks[0]).toEqual(callback); expect(client.unstable_onSuccessCallbacks[1]).toEqual(callback); }); it("should assign onResponse interceptors", async () => { const callback = interceptorCallback(); client.onResponse(callback).onResponse(callback); expect(client.unstable_onResponseCallbacks).toHaveLength(2); expect(client.unstable_onResponseCallbacks[0]).toEqual(callback); expect(client.unstable_onResponseCallbacks[1]).toEqual(callback); }); }); describe("When interceptor callbacks go into the execution loop", () => { it("should trigger unstable_modifyErrorResponse async loop", async () => { const callbackAsync = interceptorCallback({ callback: spy1, sleepTime: 20 }); const callbackSync = interceptorCallback({ callback: spy2 }); const callbackLast = interceptorCallback({ callback: spy3, sleepTime: 10 }); client.onError(callbackAsync).onError(callbackSync).onError(callbackLast); await client.unstable_modifyErrorResponse( { data: null, error: null, status: 400, success: false, extra: xhrExtra, responseTimestamp: Date.now(), requestTimestamp: Date.now(), }, request, ); testCallbacksExecution([spy1, spy2, spy3]); }); it("should trigger __modifySuccessResponse async loop", async () => { const callbackAsync = interceptorCallback({ callback: spy1, sleepTime: 20 }); const callbackSync = interceptorCallback({ callback: spy2 }); const callbackLast = interceptorCallback({ callback: spy3, sleepTime: 10 }); client.onSuccess(callbackAsync).onSuccess(callbackSync).onSuccess(callbackLast); await client.unstable_modifySuccessResponse( { data: null, error: null, status: 400, success: false, extra: xhrExtra, responseTimestamp: Date.now(), requestTimestamp: Date.now(), }, request, ); testCallbacksExecution([spy1, spy2, spy3]); }); it("should trigger __modifyResponse async loop", async () => { const callbackAsync = interceptorCallback({ callback: spy1, sleepTime: 20 }); const callbackSync = interceptorCallback({ callback: spy2 }); const callbackLast = interceptorCallback({ callback: spy3, sleepTime: 10 }); client.onResponse(callbackAsync).onResponse(callbackSync).onResponse(callbackLast); await client.unstable_modifyResponse( { data: null, error: null, status: 400, success: false, extra: xhrExtra, requestTimestamp: Date.now(), responseTimestamp: Date.now(), }, request, ); testCallbacksExecution([spy1, spy2, spy3]); }); }); describe("When interceptor returns undefined value", () => { it("should throw onError method when request is not returned", async () => { client.onError(() => undefined as any); await expect( client.unstable_modifyErrorResponse( { data: null, error: null, status: 400, success: false, extra: xhrExtra, requestTimestamp: Date.now(), responseTimestamp: Date.now(), }, request, ), ).rejects.toThrow(); }); it("should throw onSuccess method when request is not returned", async () => { client.onSuccess(() => undefined as any); await expect( client.unstable_modifySuccessResponse( { data: null, error: null, status: 400, success: false, extra: xhrExtra, requestTimestamp: Date.now(), responseTimestamp: Date.now(), }, request, ), ).rejects.toThrow(); }); it("should throw onResponse method when request is not returned", async () => { client.onResponse(() => undefined as any); await expect( client.unstable_modifyResponse( { data: null, error: null, status: 400, success: false, extra: xhrExtra, requestTimestamp: Date.now(), responseTimestamp: Date.now(), }, request, ), ).rejects.toThrow(); }); }); describe("When user wants to remove listeners", () => { it("should allow for removing interceptors on error", async () => { const firstCallback = interceptorCallback({ callback: spy1 }); const secondCallback = interceptorCallback({ callback: spy2 }); client.onError(firstCallback).onError(secondCallback); mockRequest(request, { status: 400 }); await request.send({}); client.removeOnErrorInterceptors([secondCallback]); await request.send({}); expect(spy1).toHaveBeenCalledTimes(2); expect(spy2).toHaveBeenCalledTimes(1); }); it("should allow for removing interceptors on success", async () => { mockRequest(request, { data: { data: [1, 2, 3] } }); const firstCallback = interceptorCallback({ callback: spy1 }); const secondCallback = interceptorCallback({ callback: spy2 }); client.onSuccess(firstCallback).onSuccess(secondCallback); await request.send({}); client.removeOnSuccessInterceptors([secondCallback]); await request.send({}); expect(spy1).toHaveBeenCalledTimes(2); expect(spy2).toHaveBeenCalledTimes(1); }); it("should allow for removing interceptors on response", async () => { const firstCallback = interceptorCallback({ callback: spy1 }); const secondCallback = interceptorCallback({ callback: spy2 }); client.onResponse(firstCallback).onResponse(secondCallback); mockRequest(request); await request.send({}); client.removeOnResponseInterceptors([secondCallback]); await request.send({}); expect(spy1).toHaveBeenCalledTimes(2); expect(spy2).toHaveBeenCalledTimes(1); }); }); });