test: add unit tests for relay-utils functions
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
"bun-types": "^1.3.13",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.2.5",
|
"eslint-config-next": "16.2.5",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
@@ -437,6 +438,8 @@
|
|||||||
|
|
||||||
"browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
|
"browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="],
|
||||||
|
|
||||||
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
||||||
|
|
||||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
"bun-types": "^1.3.13",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.2.5",
|
"eslint-config-next": "16.2.5",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import { test, expect, describe } from "bun:test";
|
||||||
|
import {
|
||||||
|
normalizeTargetUrl,
|
||||||
|
filterHeaders,
|
||||||
|
shouldSendBody,
|
||||||
|
isAllowedTarget,
|
||||||
|
} from "./relay-utils";
|
||||||
|
|
||||||
|
describe("relay-utils", () => {
|
||||||
|
describe("normalizeTargetUrl", () => {
|
||||||
|
test("should combine target and path", () => {
|
||||||
|
expect(normalizeTargetUrl("https://example.com", "/api/v1")).toBe("https://example.com/api/v1");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should handle trailing slash in target", () => {
|
||||||
|
expect(normalizeTargetUrl("https://example.com/", "/api/v1")).toBe("https://example.com/api/v1");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return null if target is missing", () => {
|
||||||
|
expect(normalizeTargetUrl(null, "/api/v1")).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("filterHeaders", () => {
|
||||||
|
test("should remove blocked headers", () => {
|
||||||
|
const headers = new Headers({
|
||||||
|
"content-type": "application/json",
|
||||||
|
"cookie": "secret=123",
|
||||||
|
"x-vercel-id": "123",
|
||||||
|
"cf-ray": "123",
|
||||||
|
"host": "localhost",
|
||||||
|
"x-relay-target": "test",
|
||||||
|
});
|
||||||
|
const filtered = filterHeaders(headers);
|
||||||
|
expect(filtered.has("content-type")).toBe(true);
|
||||||
|
expect(filtered.has("cookie")).toBe(false);
|
||||||
|
expect(filtered.has("x-vercel-id")).toBe(false);
|
||||||
|
expect(filtered.has("cf-ray")).toBe(false);
|
||||||
|
expect(filtered.has("host")).toBe(false);
|
||||||
|
expect(filtered.has("x-relay-target")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should remove headers starting with blocked prefixes", () => {
|
||||||
|
const headers = new Headers({
|
||||||
|
"x-vercel-custom": "val",
|
||||||
|
"cf-custom": "val",
|
||||||
|
"x-forwarded-for": "1.1.1.1",
|
||||||
|
});
|
||||||
|
const filtered = filterHeaders(headers);
|
||||||
|
expect(filtered.has("x-vercel-custom")).toBe(false);
|
||||||
|
expect(filtered.has("cf-custom")).toBe(false);
|
||||||
|
expect(filtered.has("x-forwarded-for")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("shouldSendBody", () => {
|
||||||
|
test("should return false for GET and HEAD", () => {
|
||||||
|
expect(shouldSendBody("GET")).toBe(false);
|
||||||
|
expect(shouldSendBody("HEAD")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should return true for POST, PUT, DELETE, PATCH", () => {
|
||||||
|
expect(shouldSendBody("POST")).toBe(true);
|
||||||
|
expect(shouldSendBody("PUT")).toBe(true);
|
||||||
|
expect(shouldSendBody("DELETE")).toBe(true);
|
||||||
|
expect(shouldSendBody("PATCH")).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("isAllowedTarget", () => {
|
||||||
|
test("should allow http and https", () => {
|
||||||
|
expect(isAllowedTarget("https://example.com")).toBe(true);
|
||||||
|
expect(isAllowedTarget("http://example.com")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should reject other protocols", () => {
|
||||||
|
expect(isAllowedTarget("ftp://example.com")).toBe(false);
|
||||||
|
expect(isAllowedTarget("javascript:alert(1)")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should reject invalid URLs", () => {
|
||||||
|
expect(isAllowedTarget("not-a-url")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
|
"types": ["bun-types"],
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user