Files
bytegeist-toolbox/tests/headersService.test.js
2026-07-23 05:53:14 -04:00

198 lines
4.8 KiB
JavaScript

// Import Node's built-in test tools.
const test = require("node:test");
const assert = require("node:assert/strict");
// Import the HTTP headers service functions.
const {
checkHeaders,
headersToObject,
analyzeSecurityHeaders,
isRedirectStatus,
SECURITY_HEADERS,
} = require("../src/services/headersService");
// ---------------------------------------------------------
// isRedirectStatus() tests
// ---------------------------------------------------------
test("recognizes standard redirect status codes", () => {
[301, 302, 303, 307, 308].forEach((statusCode) => {
assert.equal(isRedirectStatus(statusCode), true);
});
});
test("rejects non-redirect status codes", () => {
[200, 201, 204, 400, 404, 500].forEach((statusCode) => {
assert.equal(isRedirectStatus(statusCode), false);
});
});
// ---------------------------------------------------------
// headersToObject() tests
// ---------------------------------------------------------
test("converts Fetch Headers into a plain object", () => {
const headers = new Headers({
"content-type": "text/html",
"x-content-type-options": "nosniff",
});
const result = headersToObject(headers);
assert.deepEqual(result, {
"content-type": "text/html",
"x-content-type-options": "nosniff",
});
});
test("normalizes header names to lowercase", () => {
const headers = new Headers({
"X-Frame-Options": "DENY",
});
const result = headersToObject(headers);
assert.equal(result["x-frame-options"], "DENY");
});
// ---------------------------------------------------------
// analyzeSecurityHeaders() tests
// ---------------------------------------------------------
test("marks present security headers correctly", () => {
const headers = {
"strict-transport-security": "max-age=31536000",
"x-content-type-options": "nosniff",
};
const result = analyzeSecurityHeaders(headers);
const hsts = result.find(
(header) => header.name === "Strict-Transport-Security"
);
const contentType = result.find(
(header) => header.name === "X-Content-Type-Options"
);
assert.equal(hsts.present, true);
assert.equal(
hsts.value,
"max-age=31536000"
);
assert.equal(contentType.present, true);
assert.equal(contentType.value, "nosniff");
});
test("marks missing security headers correctly", () => {
const result = analyzeSecurityHeaders({});
result.forEach((header) => {
assert.equal(header.present, false);
assert.equal(header.value, null);
});
});
test("returns one result for every configured security header", () => {
const result = analyzeSecurityHeaders({});
assert.equal(
result.length,
SECURITY_HEADERS.length
);
});
test("returns the expected security header labels", () => {
const result = analyzeSecurityHeaders({});
const names = result.map((header) => header.name);
assert.deepEqual(names, [
"Strict-Transport-Security",
"Content-Security-Policy",
"X-Content-Type-Options",
"X-Frame-Options",
"Referrer-Policy",
"Permissions-Policy",
"Cross-Origin-Opener-Policy",
"Cross-Origin-Resource-Policy",
]);
});
// ---------------------------------------------------------
// checkHeaders() integration tests
// ---------------------------------------------------------
test("checks headers for a public website", async () => {
const result = await checkHeaders(
"https://example.com"
);
assert.equal(
result.requestedUrl,
"https://example.com"
);
assert.equal(typeof result.finalUrl, "string");
assert.equal(typeof result.statusCode, "number");
assert.equal(typeof result.statusText, "string");
assert.equal(typeof result.redirectCount, "number");
assert.equal(typeof result.headers, "object");
assert.equal(
Array.isArray(result.securityHeaders),
true
);
assert.equal(
result.securityHeaders.length,
SECURITY_HEADERS.length
);
assert.equal(
typeof result.presentSecurityHeaderCount,
"number"
);
assert.equal(
result.totalSecurityHeaderCount,
SECURITY_HEADERS.length
);
assert.equal(typeof result.checkedAt, "string");
});
test("follows redirects safely", async () => {
const result = await checkHeaders(
"http://example.com"
);
assert.equal(typeof result.finalUrl, "string");
assert.equal(result.redirectCount >= 0, true);
});
test("blocks loopback addresses", async () => {
await assert.rejects(
checkHeaders("http://127.0.0.1"),
/Local and private network addresses are not allowed/
);
});
test("blocks private network addresses", async () => {
await assert.rejects(
checkHeaders("http://192.168.1.1"),
/Local and private network addresses are not allowed/
);
});
test("rejects malformed URLs", async () => {
await assert.rejects(
checkHeaders("not a valid URL"),
/Enter a valid URL/
);
});