import { createHttpMockingServer } from "@hyper-fetch/testing"; import { Client } from "client"; import { Request } from "request"; const { resetMocks, startServer, stopServer } = createHttpMockingServer(); describe("Client [ fromJSON ]", () => { let client = new Client({ url: "shared-base-url" }); beforeAll(() => { startServer(); }); beforeEach(() => { client = new Client({ url: "shared-base-url" }); resetMocks(); }); afterAll(() => { stopServer(); }); describe("When reconstructing a request from JSON", () => { it("should return a Request class instance", () => { const original = client.createRequest()({ endpoint: "/users", method: "GET" }); const json = original.toJSON(); const restored = client.fromJSON(json); expect(restored).toBeInstanceOf(Request); }); it("should preserve endpoint from the original request", () => { const original = client.createRequest()({ endpoint: "/users/:id", method: "GET" }); const json = original.toJSON(); const restored = client.fromJSON(json); expect(restored.endpoint).toBe("/users/:id"); }); it("should preserve method from the original request", () => { const original = client.createRequest()({ endpoint: "/users", method: "POST" }); const json = original.toJSON(); const restored = client.fromJSON(json); expect(restored.method).toBe("POST"); }); it("should preserve request options through serialization", () => { const original = client.createRequest()({ endpoint: "/data", method: "PUT", cache: true, retry: 3, cacheTime: 5000, }); const json = original.toJSON(); const restored = client.fromJSON(json); expect(restored.cache).toBe(true); expect(restored.retry).toBe(3); expect(restored.cacheTime).toBe(5000); }); it("should bind the restored request to the client", () => { const original = client.createRequest()({ endpoint: "/test", method: "GET" }); const json = original.toJSON(); const restored = client.fromJSON(json); expect(restored.client).toBe(client); }); }); describe("When using type generics", () => { it("should produce the same response type as createRequest", () => { type Props = { response: { id: number; name: string } }; const created = client.createRequest()({ endpoint: "/users", method: "GET" }); const restored = client.fromJSON(created.toJSON()); type CreatedData = Awaited>["data"]; type RestoredData = Awaited>["data"]; expectTypeOf().toEqualTypeOf(); }); it("should produce the same payload type as createRequest", () => { type Props = { response: { id: number }; payload: { name: string; email: string } }; const created = client.createRequest()({ endpoint: "/users", method: "POST" }); const restored = client.fromJSON(created.toJSON()); type CreatedPayload = Parameters[0]; type RestoredPayload = Parameters[0]; expectTypeOf().toEqualTypeOf(); }); it("should produce the same error type as createRequest", () => { type Props = { error: { code: string; message: string } }; const created = client.createRequest()({ endpoint: "/fail", method: "GET" }); const restored = client.fromJSON(created.toJSON()); type CreatedError = Awaited>["error"]; type RestoredError = Awaited>["error"]; expectTypeOf().toEqualTypeOf(); }); it("should produce the same defaults as createRequest when no generics are passed", () => { const created = client.createRequest()({ endpoint: "/test", method: "GET" }); const restored = client.fromJSON(created.toJSON()); type CreatedData = Awaited>["data"]; type RestoredData = Awaited>["data"]; type CreatedPayload = Parameters[0]; type RestoredPayload = Parameters[0]; expectTypeOf().toEqualTypeOf(); expectTypeOf().toEqualTypeOf(); }); it("should produce the same endpoint params type as createRequest", () => { type Props = { response: { id: number }; endpoint: "/users/:userId" }; const created = client.createRequest()({ endpoint: "/users/:userId", method: "GET" }); const restored = client.fromJSON(created.toJSON()); type CreatedParams = Parameters[0]; type RestoredParams = Parameters[0]; expectTypeOf().toEqualTypeOf(); }); it("should produce the same query params type as createRequest", () => { type Props = { queryParams: { search?: string; page?: number } }; const created = client.createRequest()({ endpoint: "/search", method: "GET" }); const restored = client.fromJSON(created.toJSON()); type CreatedQueryParams = Parameters[0]; type RestoredQueryParams = Parameters[0]; expectTypeOf().toEqualTypeOf(); }); it("should produce matching types for all generics combined", () => { type Props = { response: { id: number }; payload: { name: string }; error: { msg: string }; queryParams: { limit: number }; endpoint: "/items/:itemId"; }; const created = client.createRequest()({ endpoint: "/items/:itemId", method: "POST" }); const restored = client.fromJSON(created.toJSON()); type CreatedData = Awaited>["data"]; type RestoredData = Awaited>["data"]; expectTypeOf().toEqualTypeOf(); type CreatedError = Awaited>["error"]; type RestoredError = Awaited>["error"]; expectTypeOf().toEqualTypeOf(); type CreatedPayload = Parameters[0]; type RestoredPayload = Parameters[0]; expectTypeOf().toEqualTypeOf(); type CreatedParams = Parameters[0]; type RestoredParams = Parameters[0]; expectTypeOf().toEqualTypeOf(); type CreatedQueryParams = Parameters[0]; type RestoredQueryParams = Parameters[0]; expectTypeOf().toEqualTypeOf(); }); }); });