Files
formbricks-formbricks/apps/web/app/lib/api/response.test.ts

367 lines
11 KiB
TypeScript

import { NextApiResponse } from "next";
import { describe, expect, test } from "vitest";
import { responses } from "./response";
describe("API Response Utilities", () => {
describe("successResponse", () => {
test("should return a success response with data", () => {
const testData = { message: "test" };
const response = responses.successResponse(testData);
expect(response.status).toBe(200);
expect(response.headers.get("Cache-Control")).toBe("private, no-store");
expect(response.headers.get("Access-Control-Allow-Origin")).toBeNull();
return response.json().then((body) => {
expect(body).toEqual({ data: testData });
});
});
test("should include CORS headers when cors is true", () => {
const testData = { message: "test" };
const response = responses.successResponse(testData, true);
expect(response.headers.get("Access-Control-Allow-Origin")).toBe("*");
expect(response.headers.get("Access-Control-Allow-Methods")).toBe("GET, POST, PUT, DELETE, OPTIONS");
expect(response.headers.get("Access-Control-Allow-Headers")).toBe("Content-Type, Authorization");
});
test("should use custom cache control header when provided", () => {
const testData = { message: "test" };
const customCache = "public, max-age=3600";
const response = responses.successResponse(testData, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("badRequestResponse", () => {
test("should return a bad request response", () => {
const message = "Invalid input";
const details = { field: "email" };
const response = responses.badRequestResponse(message, details);
expect(response.status).toBe(400);
return response.json().then((body) => {
expect(body).toEqual({
code: "bad_request",
message,
details,
});
});
});
test("should handle undefined details", () => {
const message = "Invalid input";
const response = responses.badRequestResponse(message);
expect(response.status).toBe(400);
return response.json().then((body) => {
expect(body).toEqual({
code: "bad_request",
message,
details: {},
});
});
});
test("should use custom cache control header when provided", () => {
const message = "Invalid input";
const customCache = "no-cache";
const response = responses.badRequestResponse(message, undefined, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("notFoundResponse", () => {
test("should return a not found response", () => {
const resourceType = "User";
const resourceId = "123";
const response = responses.notFoundResponse(resourceType, resourceId);
expect(response.status).toBe(404);
return response.json().then((body) => {
expect(body).toEqual({
code: "not_found",
message: `${resourceType} not found`,
details: {
resource_id: resourceId,
resource_type: resourceType,
},
});
});
});
test("should handle null resourceId", () => {
const resourceType = "User";
const response = responses.notFoundResponse(resourceType, null);
expect(response.status).toBe(404);
return response.json().then((body) => {
expect(body).toEqual({
code: "not_found",
message: `${resourceType} not found`,
details: {
resource_id: null,
resource_type: resourceType,
},
});
});
});
test("should use custom cache control header when provided", () => {
const resourceType = "User";
const resourceId = "123";
const customCache = "no-cache";
const response = responses.notFoundResponse(resourceType, resourceId, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("internalServerErrorResponse", () => {
test("should return an internal server error response", () => {
const message = "Something went wrong";
const response = responses.internalServerErrorResponse(message);
expect(response.status).toBe(500);
return response.json().then((body) => {
expect(body).toEqual({
code: "internal_server_error",
message,
details: {},
});
});
});
test("should include CORS headers when cors is true", () => {
const message = "Something went wrong";
const response = responses.internalServerErrorResponse(message, true);
expect(response.headers.get("Access-Control-Allow-Origin")).toBe("*");
expect(response.headers.get("Access-Control-Allow-Methods")).toBe("GET, POST, PUT, DELETE, OPTIONS");
expect(response.headers.get("Access-Control-Allow-Headers")).toBe("Content-Type, Authorization");
});
test("should use custom cache control header when provided", () => {
const message = "Something went wrong";
const customCache = "no-cache";
const response = responses.internalServerErrorResponse(message, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("goneResponse", () => {
test("should return a gone response", () => {
const message = "Resource no longer available";
const details = { reason: "deleted" };
const response = responses.goneResponse(message, details);
expect(response.status).toBe(410);
return response.json().then((body) => {
expect(body).toEqual({
code: "gone",
message,
details,
});
});
});
test("should handle undefined details", () => {
const message = "Resource no longer available";
const response = responses.goneResponse(message);
expect(response.status).toBe(410);
return response.json().then((body) => {
expect(body).toEqual({
code: "gone",
message,
details: {},
});
});
});
test("should use custom cache control header when provided", () => {
const message = "Resource no longer available";
const customCache = "no-cache";
const response = responses.goneResponse(message, undefined, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("methodNotAllowedResponse", () => {
test("should return a method not allowed response", () => {
const mockRes = {
req: { method: "PUT" },
} as NextApiResponse;
const allowedMethods = ["GET", "POST"];
const response = responses.methodNotAllowedResponse(mockRes, allowedMethods);
expect(response.status).toBe(405);
return response.json().then((body) => {
expect(body).toEqual({
code: "method_not_allowed",
message: "The HTTP PUT method is not supported by this route.",
details: {
allowed_methods: allowedMethods,
},
});
});
});
test("should handle missing request method", () => {
const mockRes = {} as NextApiResponse;
const allowedMethods = ["GET", "POST"];
const response = responses.methodNotAllowedResponse(mockRes, allowedMethods);
expect(response.status).toBe(405);
return response.json().then((body) => {
expect(body).toEqual({
code: "method_not_allowed",
message: "The HTTP undefined method is not supported by this route.",
details: {
allowed_methods: allowedMethods,
},
});
});
});
test("should use custom cache control header when provided", () => {
const mockRes = {
req: { method: "PUT" },
} as NextApiResponse;
const allowedMethods = ["GET", "POST"];
const customCache = "no-cache";
const response = responses.methodNotAllowedResponse(mockRes, allowedMethods, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("notAuthenticatedResponse", () => {
test("should return a not authenticated response", () => {
const response = responses.notAuthenticatedResponse();
expect(response.status).toBe(401);
return response.json().then((body) => {
expect(body).toEqual({
code: "not_authenticated",
message: "Not authenticated",
details: {
"x-Api-Key": "Header not provided or API Key invalid",
},
});
});
});
test("should use custom cache control header when provided", () => {
const customCache = "no-cache";
const response = responses.notAuthenticatedResponse(false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("unauthorizedResponse", () => {
test("should return an unauthorized response", () => {
const response = responses.unauthorizedResponse();
expect(response.status).toBe(401);
return response.json().then((body) => {
expect(body).toEqual({
code: "unauthorized",
message: "You are not authorized to access this resource",
details: {},
});
});
});
test("should use custom cache control header when provided", () => {
const customCache = "no-cache";
const response = responses.unauthorizedResponse(false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("forbiddenResponse", () => {
test("should return a forbidden response", () => {
const message = "Access denied";
const details = { reason: "insufficient_permissions" };
const response = responses.forbiddenResponse(message, false, details);
expect(response.status).toBe(403);
return response.json().then((body) => {
expect(body).toEqual({
code: "forbidden",
message,
details,
});
});
});
test("should handle undefined details", () => {
const message = "Access denied";
const response = responses.forbiddenResponse(message);
expect(response.status).toBe(403);
return response.json().then((body) => {
expect(body).toEqual({
code: "forbidden",
message,
details: {},
});
});
});
test("should use custom cache control header when provided", () => {
const message = "Access denied";
const customCache = "no-cache";
const response = responses.forbiddenResponse(message, false, undefined, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
describe("tooManyRequestsResponse", () => {
test("should return a too many requests response", () => {
const message = "Rate limit exceeded";
const response = responses.tooManyRequestsResponse(message);
expect(response.status).toBe(429);
return response.json().then((body) => {
expect(body).toEqual({
code: "too_many_requests",
message,
details: {},
});
});
});
test("should use custom cache control header when provided", () => {
const message = "Rate limit exceeded";
const customCache = "no-cache";
const response = responses.tooManyRequestsResponse(message, false, customCache);
expect(response.headers.get("Cache-Control")).toBe(customCache);
});
});
});