Files
stef-openclaw-skills/skills/flight-finder/tests/report-pdf.test.ts

77 lines
2.2 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import os from "node:os";
import path from "node:path";
import fs from "node:fs";
import { renderFlightReportPdf, ReportValidationError } from "../src/report-pdf.js";
import type { FlightReportPayload } from "../src/types.js";
import {
DFW_BLQ_2026_PROMPT_DRAFT,
normalizeFlightReportRequest
} from "../src/request-normalizer.js";
function samplePayload(): FlightReportPayload {
return {
request: normalizeFlightReportRequest(DFW_BLQ_2026_PROMPT_DRAFT).request,
sourceFindings: [
{
source: "kayak",
status: "viable",
checkedAt: "2026-03-30T21:00:00Z",
notes: ["Returned usable options."]
}
],
quotes: [
{
id: "quote-1",
source: "kayak",
legId: "outbound",
passengerGroupIds: ["pair", "solo"],
bookingLink: "https://example.com/quote-1",
itinerarySummary: "DFW -> BLQ via LHR",
totalPriceUsd: 2847,
displayPriceUsd: "$2,847"
}
],
rankedOptions: [
{
id: "primary",
title: "Best overall itinerary",
quoteIds: ["quote-1"],
totalPriceUsd: 2847,
rationale: "Best price-to-convenience tradeoff."
}
],
executiveSummary: ["Best fare currently found is $2,847 total for 3 adults."],
reportWarnings: [],
degradedReasons: [],
comparisonCurrency: "USD",
generatedAt: "2026-03-30T21:00:00Z",
lastCompletedPhase: "ranking"
};
}
test("renderFlightReportPdf writes a non-empty PDF", async () => {
const outputPath = path.join(os.tmpdir(), `flight-finder-${Date.now()}.pdf`);
await renderFlightReportPdf(samplePayload(), outputPath);
assert.ok(fs.existsSync(outputPath));
assert.ok(fs.statSync(outputPath).size > 0);
});
test("renderFlightReportPdf rejects incomplete report payloads", async () => {
const outputPath = path.join(os.tmpdir(), `flight-finder-incomplete-${Date.now()}.pdf`);
await assert.rejects(
() =>
renderFlightReportPdf(
{
...samplePayload(),
rankedOptions: [],
executiveSummary: []
},
outputPath
),
ReportValidationError
);
});