Files
stef-openclaw-skills/skills/property-assessor/tests/report-pdf.test.ts

90 lines
2.9 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import assert from "node:assert/strict";
import { ReportValidationError, renderReportPdf } from "../src/report-pdf.js";
const samplePayload = {
recipientEmails: ["buyer@example.com"],
assessmentPurpose: "investment property",
reportTitle: "Property Assessment Report",
subjectProperty: {
address: "4141 Whiteley Dr, Corpus Christi, TX 78418",
listingPrice: 149900,
propertyType: "Townhouse",
beds: 2,
baths: 2,
squareFeet: 900,
yearBuilt: 1978
},
verdict: {
decision: "only below x",
fairValueRange: "$132,000 - $138,000",
offerGuidance:
"Only attractive below ask after HOA, insurance, and medium make-ready assumptions are priced in."
},
snapshot: ["2 bed / 2 bath coastal townhouse in Flour Bluff."],
whatILike: ["Compact layout with usable bedroom count for the size."],
whatIDontLike: ["Thin margin at the current ask."],
compView: ["Need same-building or local comp confirmation."],
carryView: ["Underwrite taxes, HOA, wind/flood exposure, and maintenance together."],
risksAndDiligence: ["Confirm reserve strength and special assessment history."],
photoReview: {
status: "completed",
source: "Zillow",
attempts: ["Zillow all-photo extractor returned the full 29-photo set."],
summary: "Interior reads dated-to-average rather than turnkey."
},
publicRecords: {
jurisdiction: "Nueces Appraisal District",
assessedTotalValue: 141000,
links: [{ label: "Nueces CAD", url: "http://www.ncadistrict.com/" }]
},
sourceLinks: [
{ label: "Zillow Listing", url: "https://www.zillow.com/homedetails/example" }
]
};
test("renderReportPdf writes a non-empty PDF", async () => {
const outputPath = path.join(os.tmpdir(), `property-assessor-${Date.now()}.pdf`);
await renderReportPdf(samplePayload, outputPath);
const stat = await fs.promises.stat(outputPath);
assert.ok(stat.size > 1000);
});
test("renderReportPdf requires recipient email", async () => {
const outputPath = path.join(os.tmpdir(), `property-assessor-missing-email-${Date.now()}.pdf`);
await assert.rejects(
() =>
renderReportPdf(
{
...samplePayload,
recipientEmails: []
},
outputPath
),
ReportValidationError
);
});
test("renderReportPdf rejects a preliminary report with pending verdict", async () => {
const outputPath = path.join(os.tmpdir(), `property-assessor-preliminary-${Date.now()}.pdf`);
await assert.rejects(
() =>
renderReportPdf(
{
...samplePayload,
verdict: {
decision: "pending",
fairValueRange: "Not established",
offerGuidance: "Still needs comps and decision-grade analysis."
}
},
outputPath
),
/decision-grade|preliminary|pending/i
);
});