UNPKG

honkit

Version:

HonKit is building beautiful books using Markdown.

161 lines (155 loc) 6.15 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const child_process_1 = require("child_process"); const tmpdir_1 = require("../../fs/tmpdir"); /** * Integration tests for honkit serve rebuild behavior * * These tests verify that: * 1. SUMMARY.md changes trigger full rebuild and generate new pages * 2. New file additions are detected and processed * * This is a black-box test that starts serve, modifies files, and checks output. */ jest.setTimeout(60000); describe("serve integration", () => { let tempDir; let outputDir; let serveProcess = null; beforeEach(() => { tempDir = (0, tmpdir_1.createTmpDirWithRealPath)("honkit-serve-test-"); outputDir = path_1.default.join(tempDir, "_book"); }); afterEach(async () => { // Kill serve process if (serveProcess && !serveProcess.killed) { serveProcess.kill("SIGKILL"); await new Promise((resolve) => { serveProcess?.on("exit", resolve); setTimeout(resolve, 1000); }); } serveProcess = null; // Cleanup temp directory if (tempDir && fs_1.default.existsSync(tempDir)) { fs_1.default.rmSync(tempDir, { recursive: true, force: true }); } }); function createBookStructure() { fs_1.default.writeFileSync(path_1.default.join(tempDir, "README.md"), `# Test Book Welcome to the test book. `); fs_1.default.writeFileSync(path_1.default.join(tempDir, "SUMMARY.md"), `# Summary * [Introduction](README.md) `); } function getOutputFiles() { if (!fs_1.default.existsSync(outputDir)) return []; const files = []; const walk = (dir, prefix = "") => { const entries = fs_1.default.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name; if (entry.isDirectory()) { walk(path_1.default.join(dir, entry.name), relativePath); } else { files.push(relativePath); } } }; walk(outputDir); return files.sort(); } function startServe() { return new Promise((resolve, reject) => { const binPath = path_1.default.resolve(__dirname, "../../../bin/honkit.js"); // Use port 0 to let OS assign an available port serveProcess = (0, child_process_1.spawn)(process.execPath, [binPath, "serve", tempDir, outputDir, "--port", "0", "--lrport", "0"], { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env } }); let started = false; const checkStarted = (output) => { if (output.includes("Serving book on") && !started) { started = true; // Wait a bit for initial build to complete setTimeout(resolve, 1000); } }; serveProcess.stdout?.on("data", (data) => { checkStarted(data.toString()); }); serveProcess.stderr?.on("data", (data) => { // HonKit outputs to stderr for info/warn checkStarted(data.toString()); }); serveProcess.on("error", reject); // Timeout after 10 seconds setTimeout(() => { if (!started) { reject(new Error("Timeout waiting for serve to start")); } }, 10000); }); } function waitForFile(filePath, timeoutMs = 15000) { return new Promise((resolve, reject) => { const startTime = Date.now(); const check = () => { if (fs_1.default.existsSync(filePath)) { resolve(); } else if (Date.now() - startTime > timeoutMs) { reject(new Error(`Timeout waiting for file: ${filePath}`)); } else { setTimeout(check, 200); } }; check(); }); } describe("file watching and rebuild", () => { it("should generate new page when SUMMARY.md is updated during serve", async () => { createBookStructure(); await startServe(); // Verify initial build - only index.html expect(getOutputFiles()).toContain("index.html"); expect(getOutputFiles()).not.toContain("chapter1.html"); // Add chapter1.md fs_1.default.writeFileSync(path_1.default.join(tempDir, "chapter1.md"), `# Chapter 1 This is chapter 1. `); // Update SUMMARY.md to include chapter1 fs_1.default.writeFileSync(path_1.default.join(tempDir, "SUMMARY.md"), `# Summary * [Introduction](README.md) * [Chapter 1](chapter1.md) `); // Wait for rebuild await waitForFile(path_1.default.join(outputDir, "chapter1.html")); // Verify chapter1.html was generated expect(getOutputFiles()).toContain("chapter1.html"); }); it("should copy new asset file when added during serve", async () => { createBookStructure(); await startServe(); // Verify initial state expect(getOutputFiles()).not.toContain("notes.md"); // Add new asset file (not in SUMMARY.md) fs_1.default.writeFileSync(path_1.default.join(tempDir, "notes.md"), `# Notes These are my notes. `); // Wait for the asset to be copied await waitForFile(path_1.default.join(outputDir, "notes.md")); // Verify asset was copied expect(getOutputFiles()).toContain("notes.md"); }); }); });