185 lines
5.6 KiB
TypeScript
185 lines
5.6 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
buildJinaReaderAuditInput,
|
|
buildScreenshotOneRequests,
|
|
estimateExternalAuditCostUsd,
|
|
} from "../lib/external-audit-services";
|
|
|
|
test("estimateExternalAuditCostUsd totals managed provider usage", () => {
|
|
const estimate = estimateExternalAuditCostUsd({
|
|
openRouter: {
|
|
inputTokens: 1_500_000,
|
|
outputTokens: 250_000,
|
|
inputUsdPerMillionTokens: 0.25,
|
|
outputUsdPerMillionTokens: 1.25,
|
|
},
|
|
screenshotOne: {
|
|
screenshots: 2,
|
|
usdPerScreenshot: 0.01,
|
|
},
|
|
jina: {
|
|
requests: 4,
|
|
pages: 4,
|
|
usdPerRequest: 0.001,
|
|
usdPerPage: 0.002,
|
|
},
|
|
pageSpeed: {
|
|
requests: 2,
|
|
},
|
|
});
|
|
|
|
assert.equal(estimate.totalUsd, 0.7195);
|
|
assert.deepEqual(estimate.byProvider, {
|
|
openRouter: 0.6875,
|
|
screenshotOne: 0.02,
|
|
jina: 0.012,
|
|
pageSpeed: 0,
|
|
});
|
|
});
|
|
|
|
test("estimateExternalAuditCostUsd clamps negative usage and prices to zero", () => {
|
|
const estimate = estimateExternalAuditCostUsd({
|
|
openRouter: {
|
|
inputTokens: -1_000_000,
|
|
outputTokens: 100_000,
|
|
inputUsdPerMillionTokens: 0.25,
|
|
outputUsdPerMillionTokens: -1.25,
|
|
},
|
|
screenshotOne: {
|
|
screenshots: -2,
|
|
usdPerScreenshot: 0.01,
|
|
},
|
|
jina: {
|
|
requests: 4,
|
|
pages: -4,
|
|
usdPerRequest: -0.001,
|
|
usdPerPage: 0.002,
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(estimate.byProvider, {
|
|
openRouter: 0,
|
|
screenshotOne: 0,
|
|
jina: 0,
|
|
pageSpeed: 0,
|
|
});
|
|
assert.equal(estimate.totalUsd, 0);
|
|
});
|
|
|
|
test("buildScreenshotOneRequests creates stable desktop and mobile URLs", () => {
|
|
const requests = buildScreenshotOneRequests({
|
|
accessKey: "sso_secret_key",
|
|
targetUrl: "https://example.com/landing?utm=abc",
|
|
});
|
|
|
|
assert.equal(requests.length, 2);
|
|
assert.deepEqual(
|
|
requests.map((request) => request.viewport),
|
|
["desktop", "mobile"],
|
|
);
|
|
|
|
const desktop = new URL(requests[0]?.url ?? "");
|
|
assert.equal(desktop.searchParams.get("access_key"), "sso_secret_key");
|
|
assert.equal(desktop.searchParams.get("url"), "https://example.com/landing?utm=abc");
|
|
assert.equal(desktop.searchParams.get("viewport_width"), "1280");
|
|
assert.equal(desktop.searchParams.get("viewport_height"), "900");
|
|
assert.equal(desktop.searchParams.get("device_scale_factor"), "1");
|
|
assert.equal(desktop.searchParams.get("full_page"), "true");
|
|
assert.equal(desktop.searchParams.get("block_cookie_banners"), "true");
|
|
assert.equal(desktop.searchParams.get("block_ads"), "true");
|
|
assert.equal(desktop.searchParams.get("block_trackers"), "true");
|
|
|
|
const mobile = new URL(requests[1]?.url ?? "");
|
|
assert.equal(mobile.searchParams.get("viewport_width"), "390");
|
|
assert.equal(mobile.searchParams.get("viewport_height"), "844");
|
|
assert.equal(mobile.searchParams.get("device_scale_factor"), "2");
|
|
assert.equal(mobile.searchParams.get("full_page"), "true");
|
|
});
|
|
|
|
test("buildScreenshotOneRequests rejects non-web target URLs without leaking secrets", () => {
|
|
assert.throws(
|
|
() =>
|
|
buildScreenshotOneRequests({
|
|
accessKey: "sso_secret_key",
|
|
targetUrl: "ftp://example.com/landing",
|
|
}),
|
|
(error) => {
|
|
assert.equal(error instanceof Error, true);
|
|
assert.equal((error as Error).message.includes("sso_secret_key"), false);
|
|
assert.match((error as Error).message, /http.*https/i);
|
|
return true;
|
|
},
|
|
);
|
|
});
|
|
|
|
test("buildScreenshotOneRequests does not leak the access key in validation errors", () => {
|
|
assert.throws(
|
|
() =>
|
|
buildScreenshotOneRequests({
|
|
accessKey: "sso_secret_key",
|
|
targetUrl: "not a url",
|
|
}),
|
|
(error) => {
|
|
assert.equal(error instanceof Error, true);
|
|
assert.equal((error as Error).message.includes("sso_secret_key"), false);
|
|
assert.match((error as Error).message, /target url/i);
|
|
return true;
|
|
},
|
|
);
|
|
});
|
|
|
|
test("buildJinaReaderAuditInput rejects non-web base and page URLs", () => {
|
|
assert.throws(
|
|
() =>
|
|
buildJinaReaderAuditInput({
|
|
baseUrl: "file:///tmp/site.html",
|
|
maxMarkdownChars: 100,
|
|
}),
|
|
/http.*https/i,
|
|
);
|
|
|
|
assert.throws(
|
|
() =>
|
|
buildJinaReaderAuditInput({
|
|
baseUrl: "https://example.com",
|
|
pages: [{ url: "ftp://example.com/kontakt", markdown: "Kontakt" }],
|
|
maxMarkdownChars: 100,
|
|
}),
|
|
/http.*https/i,
|
|
);
|
|
});
|
|
|
|
test("buildJinaReaderAuditInput prepares capped markdown for relevant pages", () => {
|
|
const input = buildJinaReaderAuditInput({
|
|
baseUrl: "https://example.com",
|
|
pages: [
|
|
{ url: "https://example.com", markdown: "# Home\nWillkommen auf der Startseite." },
|
|
{ url: "https://example.com/kontakt", markdown: "Kontaktformular und Telefonnummer." },
|
|
{ url: "https://example.com/impressum", markdown: "Impressum mit Anbieterkennzeichnung." },
|
|
{ url: "https://example.com/leistungen", markdown: "Leistungen fuer Webdesign und SEO." },
|
|
{ url: "https://example.com/ueber-uns", markdown: "Ueber uns und Arbeitsweise." },
|
|
],
|
|
maxMarkdownChars: 95,
|
|
});
|
|
|
|
assert.deepEqual(
|
|
input.pages.map((page) => page.path),
|
|
["/", "/kontakt", "/impressum", "/leistungen", "/ueber-uns"],
|
|
);
|
|
assert.deepEqual(
|
|
input.readerUrls,
|
|
[
|
|
"https://r.jina.ai/https://example.com/",
|
|
"https://r.jina.ai/https://example.com/kontakt",
|
|
"https://r.jina.ai/https://example.com/impressum",
|
|
"https://r.jina.ai/https://example.com/leistungen",
|
|
"https://r.jina.ai/https://example.com/ueber-uns",
|
|
],
|
|
);
|
|
assert.equal(input.markdown.length <= 95, true);
|
|
assert.match(input.markdown, /Source: https:\/\/example.com/);
|
|
assert.match(input.markdown, /\[truncated to 95 chars\]$/);
|
|
});
|