@hyper-fetch/core
Version:
Cache, Queue and Persist your requests no matter if you are online or offline!
226 lines (181 loc) • 6.94 kB
text/typescript
import { createHttpMockingServer } from "@hyper-fetch/testing";
import type { QueryParamsType } from "../../../src";
import { Client, Request } from "../../../src";
const { resetMocks, startServer, stopServer, mockRequest } = createHttpMockingServer();
describe("Fetch Adapter [ Base ]", () => {
let client = new Client({ url: "shared-base-url" });
let request = client.createRequest()({ endpoint: "/shared-endpoint" });
beforeAll(() => {
startServer();
});
beforeEach(() => {
client = new Client({ url: "shared-base-url" });
request = client.createRequest()({ endpoint: "/shared-endpoint" });
resetMocks();
vi.resetAllMocks();
});
afterAll(() => {
stopServer();
});
it("should allow for setting custom header", async () => {
// The queue should receive request with the appropriate header
const spy = vi.fn(client.fetchDispatcher.add);
vi.spyOn(client.fetchDispatcher, "add").mockImplementation(spy);
const header = { it: "works" };
const c = request.setHeaders(header);
mockRequest(request);
await c.send({});
expect(c.headers).toEqual(header);
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls[0][0].headers).toEqual(header);
});
it("should allow for setting auth", async () => {
// The queue should receive request with the appropriate header
const spy = vi.fn(client.fetchDispatcher.add);
vi.spyOn(client.fetchDispatcher, "add").mockImplementation(spy);
mockRequest(request);
expect(request.auth).toBe(true);
const c = request.setAuth(false);
await c.send({});
expect(c.auth).toBe(false);
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls[0][0].auth).toBe(false);
});
it("should allow for setting custom params", async () => {
// The queue should receive request with the appropriate header
const comm = client.createRequest<{ queryParams: QueryParamsType }>()({
endpoint: "/some-endpoint/:shopId/:productId",
});
const spy = vi.fn(client.fetchDispatcher.add);
vi.spyOn(client.fetchDispatcher, "add").mockImplementation(spy);
const params = { shopId: 11, productId: 1 };
const c = comm.setParams(params);
mockRequest(c);
await c.send({
queryParams: {},
});
expect(c.params).toEqual(params);
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls[0][0].params).toEqual(params);
});
it("should allow for setting data to the request", async () => {
const spy = vi.fn(client.fetchDispatcher.add);
vi.spyOn(client.fetchDispatcher, "add").mockImplementation(spy);
const data = {
userId: 11,
role: "ADMIN",
};
const req = client.createRequest<{ response: void; payload: { userId: number; role: string } }>()({
endpoint: "/shared-endpoint",
});
const c = req.setPayload(data);
mockRequest(c);
await c.send({});
expect(c.payload).toStrictEqual(data);
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls[0][0].payload).toEqual(data);
});
it("Should allow for setting queryParams", async () => {
const queryParams = { userId: 11 };
const comm = client.createRequest<{ queryParams: QueryParamsType }>()({
endpoint: "/some-endpoint/",
});
mockRequest(comm);
const spy = vi.fn(client.fetchDispatcher.add);
vi.spyOn(client.fetchDispatcher, "add").mockImplementation(spy);
const requestQueryParams = comm.setQueryParams(queryParams);
requestQueryParams.send({});
expect(requestQueryParams.queryParams).toStrictEqual(queryParams);
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls[0][0].queryParams).toStrictEqual(queryParams);
});
it("Should allow to validate before sending request", async () => {
const message = "something went wrong";
const mapper = () => {
throw new Error(message);
};
const mapperRequest = client
.createRequest<{ response: null }>()({ endpoint: "/some-endpoint/" })
.setRequestMapper(mapper);
mockRequest(mapperRequest);
const { data, error } = await mapperRequest.send({});
expect(error?.message).toStrictEqual(message);
expect(data).toBe(null);
});
it("Should allow to validate response", async () => {
const message = "something went wrong";
const mapperRequest = client
.createRequest<{ response: null }>()({ endpoint: "/some-endpoint/" })
.setResponseMapper((res) => {
return { ...res, data: null, error: new Error(message) } as typeof res;
});
mockRequest(mapperRequest);
const { data, error } = await mapperRequest.send({});
expect(error?.message).toStrictEqual(message);
expect(data).toBe(null);
});
it("Should allow to validate in data mapper", async () => {
const message = "something went wrong";
const mapper = () => {
throw new Error(message);
};
const mapperRequest = client
.createRequest<{ response: null }>()({ endpoint: "/some-endpoint/" })
.setPayloadMapper(mapper);
mockRequest(mapperRequest);
const { data, error } = await mapperRequest.send({});
expect(error?.message).toStrictEqual(message);
expect(data).toBe(null);
});
describe("read()", () => {
it("should return cached data when available", async () => {
const cachedData = {
data: { foo: "bar" },
status: 200,
};
await request
.setMock(() => ({
data: { foo: "bar" } as any,
status: 200,
}))
.send();
const result = request.read();
expect(result).toEqual({
...cachedData,
error: null,
extra: request.client.adapter.defaultExtra,
success: true,
requestTimestamp: expect.any(Number),
responseTimestamp: expect.any(Number),
});
});
it("should return undefined when no cached data exists", () => {
// Ensure cache is empty
client.cache.clear();
const result = request.read();
expect(result).toBeUndefined();
});
});
describe("fromJSON()", () => {
it("should reconstruct a request from its JSON representation", () => {
const original = client
.createRequest<{ response: { id: number }; payload: { name: string } }>()({
endpoint: "/users/:userId",
method: "POST",
})
.setHeaders({ "X-Custom": "value" })
.setAuth(false)
.setRetry(3)
.setRetryTime(500);
const json = original.toJSON();
const restored = Request.fromJSON(client, json);
expect(restored).toBeInstanceOf(Request);
expect(restored.endpoint).toBe(original.endpoint);
expect(restored.method).toBe(original.method);
expect(restored.headers).toStrictEqual(original.headers);
expect(restored.auth).toBe(original.auth);
expect(restored.retry).toBe(original.retry);
expect(restored.retryTime).toBe(original.retryTime);
});
});
});