test: add prose-fixture end-to-end smoke for kitchen view (task 0003)

Pull a reduced end-to-end smoke forward into the slice so the view flow
is exercised over a real on-disk recipe, not just a temp file.

Add fixtures/prose.md — a recipe using only this slice's modelled
constructs (frontmatter, headings, plain paragraphs) so it renders
losslessly. integration_test now runs `kitchen view fixtures/prose.md`
as a subprocess and asserts the frontmatter, separator, headings,
paragraphs, and flat document order end-to-end. smoke_test covers
`kitchen --help` exiting 0 with the view command listed.

The full fixtures/basic.md smoke remains task 0007, which needs 0004's
richer nodes before that fixture renders losslessly.
This commit is contained in:
2026-07-26 08:19:26 -04:00
parent d1c1f330c5
commit 97ecc86d63
4 changed files with 71 additions and 24 deletions

View File

@@ -1,33 +1,43 @@
import { describe, expect, test } from "bun:test";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { runCli, stripAnsi } from "./test-support.ts";
const CLI = `${import.meta.dir}/index.ts`;
const FIXTURE = join(import.meta.dir, "..", "..", "..", "fixtures", "prose.md");
describe("cli — integration", () => {
test("invokes core parser and produces output for a real fixture file", async () => {
const dir = mkdtempSync(join(tmpdir(), "kitchen-md-"));
const file = join(dir, "recipe.md");
writeFileSync(
file,
"---\ntitle: Test Recipe\nservings: 2\n---\n\n# Heading One\n\nA plain paragraph of prose.\n",
);
test("renders a real recipe fixture end-to-end", async () => {
const { exitCode, stdout } = await runCli(["view", FIXTURE], CLI);
const output = stripAnsi(stdout);
const lines = output.split("\n");
const lineOf = (needle: string): number => lines.findIndex((line) => line.includes(needle));
try {
const { exitCode, stdout } = await runCli(["view", file], CLI);
const output = stripAnsi(stdout);
expect(exitCode).toBe(0);
expect(exitCode).toBe(0);
expect(output).toContain("title: Test Recipe");
expect(output).toContain("servings: 2");
expect(output).toMatch(/─+/);
expect(output).toContain("Heading One");
expect(output).toContain("A plain paragraph of prose.");
} finally {
rmSync(dir, { recursive: true, force: true });
}
expect(output).toContain("title: Buttered Toast");
expect(output).toContain("servings: 2");
expect(output).toContain("tags:");
expect(output).toContain("breakfast");
expect(output).toContain("simple");
expect(lines.some((line) => /^─+$/.test(line))).toBe(true);
expect(output).toContain("Buttered Toast");
expect(output).toContain("Method");
expect(output).toContain("Timing");
expect(output).toContain("Serving");
expect(output).toContain("The simplest breakfast");
expect(output).toContain("Toast the bread until golden on both sides.");
expect(output).toContain("Spread the butter while the toast is still warm");
expect(output).toContain("Cut into triangles and serve at once.");
const separatorLine = lines.findIndex((line) => /^─+$/.test(line));
expect(lineOf("servings: 2")).toBeLessThan(separatorLine);
expect(separatorLine).toBeLessThan(lineOf("Method"));
expect(lineOf("Method")).toBeLessThan(lineOf("Timing"));
expect(lineOf("Timing")).toBeLessThan(lineOf("Serving"));
expect(lineOf("Method")).toBeLessThan(lineOf("Toast the bread until golden on both sides."));
});
});

View File

@@ -1,6 +1,13 @@
import { describe, test } from "bun:test";
import { describe, expect, test } from "bun:test";
import { runCli } from "./test-support.ts";
describe("smoke", () => {
test.todo("kitchen --help exits with code 0");
test("kitchen --help exits with code 0", async () => {
const { exitCode, stdout } = await runCli(["--help"], `${import.meta.dir}/index.ts`);
expect(exitCode).toBe(0);
expect(stdout).toMatch(/view/);
});
test.todo("kitchen parse <fixture> outputs structured JSON covering all annotation types");
});