Files
content-factory/apps/frontend/tests/article_review.model.test.mjs

95 lines
2.9 KiB
JavaScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import ts from "typescript";
const testDir = path.dirname(fileURLToPath(import.meta.url));
const sourcePath = path.resolve(testDir, "../src/features/article-review/model.ts");
const source = readFileSync(sourcePath, "utf8");
const compiled = ts.transpileModule(source, {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 },
});
const moduleExports = {};
new Function("exports", compiled.outputText)(moduleExports);
const { buildReviewIssueRows, buildFinalReviewSummary } = moduleExports;
const seoReport = {
id: "11111111-1111-1111-1111-111111111111",
article_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
review_kind: "SEO",
draft_id: "dddddddd-dddd-dddd-dddd-dddddddddddd",
score: 72,
issues: [
{
id: "meta-description-length",
suggestion_id: "22222222-2222-2222-2222-222222222222",
severity: "HIGH",
location: "meta_description",
message: "Meta description too short.",
suggested_fix: "Use 120-160 chars.",
suggested_rewrite: "Expanded meta description text.",
status: "PENDING",
},
],
recommended_slug: "seo-language-review-guide",
recommended_title: "SEO Language Review Guide",
schema_json: { "@type": "Article" },
rules_snapshot: { meta_description_min: 120 },
created_at: "2026-05-22T12:00:00Z",
};
const languageReport = {
...seoReport,
id: "33333333-3333-3333-3333-333333333333",
review_kind: "LANGUAGE",
issues: [
{
id: "long-sentence",
suggestion_id: "44444444-4444-4444-4444-444444444444",
severity: "MEDIUM",
location: "body_markdown",
message: "Sentence exceeds 24 words.",
suggested_fix: "Split sentence.",
suggested_rewrite: "This sentence is shorter.",
status: "ACCEPTED",
},
],
};
const rows = buildReviewIssueRows(seoReport, languageReport);
assert.equal(rows.length, 2);
assert.equal(rows[0].reviewKind, "SEO");
assert.equal(rows[0].suggestionId, "22222222-2222-2222-2222-222222222222");
assert.equal(rows[1].reviewKind, "LANGUAGE");
assert.equal(rows[1].status, "ACCEPTED");
const summary = buildFinalReviewSummary({
article_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
unresolved_count: 2,
unresolved_issues: [
{
review_kind: "SEO",
suggestion_id: "22222222-2222-2222-2222-222222222222",
severity: "HIGH",
location: "meta_description",
message: "Meta description too short.",
status: "PENDING",
},
{
review_kind: "LANGUAGE",
suggestion_id: "55555555-5555-5555-5555-555555555555",
severity: "MEDIUM",
location: "body_markdown",
message: "Sentence exceeds 24 words.",
status: "PENDING",
},
],
});
assert.equal(summary.unresolvedCount, 2);
assert.equal(summary.unresolvedTitles.length, 2);
assert.ok(summary.unresolvedTitles[0].startsWith("SEO:"));