262 lines
8.4 KiB
TypeScript
262 lines
8.4 KiB
TypeScript
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",
|
|
},
|
|
);
|
|
});
|
|
});
|