- Report p33 table: no Kranti column (no producer; materials.kranti stays blocked). - Report p53 table: the "SAV" column was the with-Lagna total (386). Split in the reader into SAV / Lagna BAV / SAV + Lagna with a totals row; ashtakavarga.py is untouched (frozen rectification identity, ERR-115). - /api/chart ascendant carries nakshatra / pada / lord (_nakshatra_fields shared with the nine bodies); chart cache schema 4 -> 5. - /api/varga_full bodies carry dignity_level from varga_dignity_level, the function the Vimsopaka path now shares (A/B identical); the chart page shows the D1 status wording and no longer derives a three-level dignity itself. - Report page draws each chart once: the trailing block skips charts the body already fenced (same rule as the export); the birth-time caveat moves under the body's chart heading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
49 lines
2.7 KiB
TypeScript
49 lines
2.7 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import React from "react";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import test from "node:test";
|
|
|
|
import { ReportCalculationCharts } from "../src/components/personal-report/report-calculation-charts.tsx";
|
|
import { buildReportExportBlocks } from "../src/lib/report-export-blocks.ts";
|
|
import { fencedReportChartIds } from "../src/lib/report-chart-block.ts";
|
|
import { assembleLongformCharts } from "../src/lib/personal-report-generation.ts";
|
|
|
|
Object.assign(globalThis, { React });
|
|
|
|
// Real engine output and its real reader body (fictional chart).
|
|
const fixture = JSON.parse(readFileSync(new URL("./fixtures/report-density-fictional-reader.json", import.meta.url), "utf8"));
|
|
const engine = JSON.parse(readFileSync(new URL("./fixtures/report-density-fictional-engine.json", import.meta.url), "utf8"));
|
|
const charts = assembleLongformCharts(engine, "ev-cover-longform");
|
|
|
|
function render(markdown: string, language: "zh" | "en" = "zh"): string {
|
|
return renderToStaticMarkup(React.createElement(ReportCalculationCharts, { charts, markdown, language }));
|
|
}
|
|
|
|
// BUG-1203: the body already drew these charts; the tail drew them again.
|
|
test("a report whose body draws every chart has no trailing chart section", () => {
|
|
const drawn = fencedReportChartIds(fixture.markdown);
|
|
assert.ok(charts.length > 0);
|
|
for (const chart of charts) assert.ok(drawn.has(chart.id), chart.id);
|
|
assert.equal(render(fixture.markdown), "");
|
|
assert.equal(render(fixture.markdown, "en"), "");
|
|
});
|
|
|
|
test("an older body without chart fences keeps its charts, without the moved caveat", () => {
|
|
const markup = render("# 报告\n\n正文");
|
|
assert.match(markup, /<h2>分盘核对<\/h2>/);
|
|
assert.equal((markup.match(/personal-report-chart-card/g) ?? []).length, charts.filter(chart => chart.houses.some(house => house.occupants.length)).length);
|
|
assert.doesNotMatch(markup, /出生时间敏感/);
|
|
});
|
|
|
|
test("the page and the export skip the same charts", () => {
|
|
const first = /```jyotish-chart\n[\s\S]*?```/.exec(fixture.markdown)![0];
|
|
const drawn = [...fencedReportChartIds(first)];
|
|
assert.equal(drawn.length, 1);
|
|
const markup = render(first);
|
|
const pageIds = charts.filter(chart => !drawn.includes(chart.id) && chart.houses.some(house => house.occupants.length)).map(chart => chart.id);
|
|
assert.equal((markup.match(/personal-report-chart-card/g) ?? []).length, pageIds.length);
|
|
const exported = buildReportExportBlocks({ markdown: first, charts }).filter(block => block.group === "chart" && !/^chart:[^:]+:\d+$/.test(block.id)); // fence charts carry an occurrence suffix
|
|
assert.deepEqual(exported.map(block => block.id.replace(/^chart:/, "")), pageIds);
|
|
});
|