require("ts-node/register/transpile-only"); const { expect } = require("chai"); const express = require("express"); const http = require("http"); const fs = require("fs"); const os = require("os"); const path = require("path"); const { createReviewConsentPage, isReviewConsentPagePath, } = require("../src/server/review-consent-page"); describe("isolated review consent page", function () { let server, directory, manifest; beforeEach(async function () { directory = fs.mkdtempSync(path.join(os.tmpdir(), "review-page-")); manifest = path.join(directory, "manifest.json"); const app = express(); const page = createReviewConsentPage(manifest); app.use((req, res) => isReviewConsentPagePath(req.path) ? page(req, res) : res.status(418).end(), ); server = await new Promise((resolve) => { const s = app.listen(0, "127.0.0.1", () => resolve(s)); }); }); afterEach(async function () { await new Promise((resolve) => server.close(resolve)); fs.rmSync(directory, { recursive: true, force: true }); }); function get(url, method = "GET") { return new Promise((resolve, reject) => { const req = http.request( { hostname: "127.0.0.1", port: server.address().port, path: url, method, }, (res) => { let body = ""; res.on("data", (chunk) => { body += chunk; }); res.on("end", () => resolve({ status: res.statusCode, headers: res.headers, body }), ); }, ); req.on("error", reject); req.end(); }); } it("serves only first-party assets with no inline scripts or external frames", async function () { const response = await get("/review-link"); expect(response.status).equal(200); expect(response.headers["cache-control"]).equal("no-store"); expect(response.headers["referrer-policy"]).equal("no-referrer"); expect(response.headers["x-frame-options"]).equal("DENY"); expect(response.headers["content-security-policy"]) .include("script-src 'self'") .include("frame-ancestors 'none'"); expect(response.body).include('name="review-consent-page"'); expect(response.body).not.match(/https?:|kofi|ko-fi|/i); expect(response.body.match(/