import { beforeEach, describe, expect, it, vi } from "vitest"; const apiClient = { get: vi.fn(), post: vi.fn(), put: vi.fn(), patch: vi.fn(), delete: vi.fn(), }; vi.mock("./apiClient", () => ({ default: apiClient, })); describe("devApi", () => { beforeEach(() => { apiClient.get.mockReset(); apiClient.post.mockReset(); apiClient.put.mockReset(); apiClient.patch.mockReset(); apiClient.delete.mockReset(); }); it("fetches list and detail resources with expected query parameters", async () => { const { fetchClients, fetchDevStats, fetchDevRPUsageDaily, fetchTenants, fetchClient, fetchClientRelations, fetchRPUserMetadata, fetchDevUsers, fetchConsents, fetchDevAuditLogs, fetchMyTenants, fetchDeveloperRequestStatus, fetchDeveloperRequests, listIdpConfigsForClient, } = await import("./devApi"); apiClient.get.mockResolvedValue({ data: { ok: true } }); await fetchClients(); await fetchDevStats(); await fetchDevRPUsageDaily({ days: 30, period: "week" }); await fetchTenants(25, 50, "tenant-parent"); await fetchClient("client-a"); await fetchClientRelations("client-a"); await fetchRPUserMetadata("client-a", "user-a"); await fetchDevUsers("admin", 5, "client-a"); await fetchConsents("user-a", "client-a", "active"); await fetchDevAuditLogs(10, "cursor-a", { action: "client.update", client_id: "client-a", status: "success", tenant_id: "tenant-a", }); await fetchMyTenants(); await fetchDeveloperRequestStatus("tenant-a"); await fetchDeveloperRequests("pending"); await listIdpConfigsForClient("client-a"); expect(apiClient.get).toHaveBeenCalledWith("/dev/clients"); expect(apiClient.get).toHaveBeenCalledWith("/dev/stats"); expect(apiClient.get).toHaveBeenCalledWith("/dev/rp-usage/daily", { params: { days: 30, period: "week" }, }); expect(apiClient.get).toHaveBeenCalledWith("/tenants", { params: { limit: 25, offset: 50, parentId: "tenant-parent" }, }); expect(apiClient.get).toHaveBeenCalledWith("/dev/clients/client-a"); expect(apiClient.get).toHaveBeenCalledWith( "/dev/clients/client-a/relations", ); expect(apiClient.get).toHaveBeenCalledWith( "/dev/clients/client-a/users/user-a/metadata", ); expect(apiClient.get).toHaveBeenCalledWith("/dev/users", { params: { search: "admin", limit: 5, clientId: "client-a" }, }); expect(apiClient.get).toHaveBeenCalledWith("/dev/consents", { params: { subject: "user-a", client_id: "client-a", status: "active" }, }); expect(apiClient.get).toHaveBeenCalledWith("/dev/audit-logs", { params: { limit: 10, cursor: "cursor-a", action: "client.update", client_id: "client-a", status: "success", tenant_id: "tenant-a", }, }); expect(apiClient.get).toHaveBeenCalledWith("/dev/my-tenants"); expect(apiClient.get).toHaveBeenCalledWith( "/dev/developer-request/status", { params: { tenantId: "tenant-a" }, }, ); expect(apiClient.get).toHaveBeenCalledWith("/dev/developer-request/list", { params: { status: "pending" }, }); expect(apiClient.get).toHaveBeenCalledWith("/dev/clients/client-a/idps"); }); it("omits optional consent filters when they are empty or all", async () => { const { fetchConsents, revokeConsent } = await import("./devApi"); apiClient.get.mockResolvedValue({ data: { items: [] } }); apiClient.delete.mockResolvedValue({ data: {} }); await fetchConsents("user-a", undefined, "all"); await revokeConsent("user-a"); expect(apiClient.get).toHaveBeenCalledWith("/dev/consents", { params: { subject: "user-a" }, }); expect(apiClient.delete).toHaveBeenCalledWith("/dev/consents", { params: { subject: "user-a" }, }); }); it("sends mutation requests to the documented dev endpoints", async () => { const { addClientRelation, removeClientRelation, updateRPUserMetadata, updateClientStatus, createClient, updateClient, rotateClientSecret, refreshHeadlessJwksCache, revokeHeadlessJwksCache, deleteClient, revokeConsent, createIdpConfigForClient, updateIdpConfig, deleteIdpConfig, requestDeveloperAccess, approveDeveloperRequest, rejectDeveloperRequest, cancelDeveloperRequestApproval, } = await import("./devApi"); apiClient.post.mockResolvedValue({ data: { ok: true } }); apiClient.put.mockResolvedValue({ data: { ok: true } }); apiClient.patch.mockResolvedValue({ data: { ok: true } }); apiClient.delete.mockResolvedValue({ data: {} }); await addClientRelation("client-a", { relation: "admins", userId: "user-a", }); await removeClientRelation("client-a", "admins", "User:user-a"); await updateRPUserMetadata("client-a", "user-a", { approvalLevel: "A" }); await updateClientStatus("client-a", "inactive"); await createClient({ id: "client-a", name: "Console App" }); await updateClient("client-a", { name: "Console App Updated" }); await rotateClientSecret("client-a"); await refreshHeadlessJwksCache("client-a"); await revokeHeadlessJwksCache("client-a"); await deleteClient("client-a"); await revokeConsent("user-a", "client-a"); await createIdpConfigForClient({ client_id: "client-a", provider_type: "oidc", display_name: "OIDC Provider", status: "active", }); await updateIdpConfig("client-a", "idp-a", { status: "inactive" }); await deleteIdpConfig("client-a", "idp-a"); await requestDeveloperAccess({ name: "Dev User", organization: "Hanmac", reason: "Need RP access", tenantId: "tenant-a", }); await approveDeveloperRequest(1, "approved"); await rejectDeveloperRequest(2, "rejected"); await cancelDeveloperRequestApproval(3, "cancelled"); expect(apiClient.post).toHaveBeenCalledWith( "/dev/clients/client-a/relations", { relation: "admins", userId: "user-a" }, ); expect(apiClient.delete).toHaveBeenCalledWith( "/dev/clients/client-a/relations", { params: { relation: "admins", subject: "User:user-a" }, }, ); expect(apiClient.put).toHaveBeenCalledWith( "/dev/clients/client-a/users/user-a/metadata", { metadata: { approvalLevel: "A" } }, ); expect(apiClient.patch).toHaveBeenCalledWith( "/dev/clients/client-a/status", { status: "inactive", }, ); expect(apiClient.post).toHaveBeenCalledWith("/dev/clients", { id: "client-a", name: "Console App", }); expect(apiClient.put).toHaveBeenCalledWith("/dev/clients/client-a", { name: "Console App Updated", }); expect(apiClient.post).toHaveBeenCalledWith( "/dev/clients/client-a/secret/rotate", ); expect(apiClient.post).toHaveBeenCalledWith( "/dev/clients/client-a/headless-jwks/refresh", ); expect(apiClient.delete).toHaveBeenCalledWith( "/dev/clients/client-a/headless-jwks/cache", ); expect(apiClient.delete).toHaveBeenCalledWith("/dev/clients/client-a"); expect(apiClient.delete).toHaveBeenCalledWith("/dev/consents", { params: { subject: "user-a", client_id: "client-a" }, }); expect(apiClient.post).toHaveBeenCalledWith("/dev/clients/client-a/idps", { client_id: "client-a", provider_type: "oidc", display_name: "OIDC Provider", status: "active", }); expect(apiClient.put).toHaveBeenCalledWith( "/dev/clients/client-a/idps/idp-a", { status: "inactive", }, ); expect(apiClient.delete).toHaveBeenCalledWith( "/dev/clients/client-a/idps/idp-a", ); expect(apiClient.post).toHaveBeenCalledWith("/dev/developer-request", { name: "Dev User", organization: "Hanmac", reason: "Need RP access", tenantId: "tenant-a", }); expect(apiClient.post).toHaveBeenCalledWith( "/dev/developer-request/1/approve", { adminNotes: "approved", }, ); expect(apiClient.post).toHaveBeenCalledWith( "/dev/developer-request/2/reject", { adminNotes: "rejected", }, ); expect(apiClient.post).toHaveBeenCalledWith( "/dev/developer-request/3/cancel-approval", { adminNotes: "cancelled", }, ); }); });