import assert from "node:assert/strict"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import test from "node:test"; import { validateArtifact } from "../lib/validation"; async function fixture(files: Record) { const root = await fs.mkdtemp(path.join(os.tmpdir(), "rednote-validator-")); for (const [name, content] of Object.entries(files)) { const target = path.join(root, name); await fs.mkdir(path.dirname(target), { recursive: true }); await fs.writeFile(target, content); } return root; } test("accepts a minimal offline artifact", async (t) => { const root = await fixture({ "index.html": '', "assets/main.js": 'document.body.addEventListener("click", function () {});', "assets/style.css": "body { color: #333; }", }); t.after(() => fs.rm(root, { recursive: true, force: true })); const report = await validateArtifact(root); assert.equal(report.status, "passed"); assert.match(report.auditOutput, /PASS/); }); test("reports forbidden APIs, inline handlers and missing resources", async (t) => { const root = await fixture({ "index.html": '', "main.js": 'fetch("/api");', }); t.after(() => fs.rm(root, { recursive: true, force: true })); const report = await validateArtifact(root); const codes = report.issues.map((issue) => issue.code); assert.equal(report.status, "failed"); assert.ok(codes.includes("NETWORK_FETCH")); assert.ok(codes.includes("INLINE_EVENT")); assert.ok(codes.includes("MISSING_RESOURCE")); });