refactor(tests): centralize test harness boilerplate into bundle.mjs helper
This commit is contained in:
parent
1729f7c236
commit
43a03272bf
9 changed files with 107 additions and 150 deletions
55
tests/helpers/bundle.mjs
Normal file
55
tests/helpers/bundle.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Shared test-harness bundler.
|
||||||
|
//
|
||||||
|
// Every run-*-test.mjs used to hand-roll the same esbuild boilerplate:
|
||||||
|
// write temp entry (optional) -> esbuild.build(bundle/node/esm/silent)
|
||||||
|
// -> dynamic import of the artifact -> rmSync cleanup.
|
||||||
|
// This module is that sequence, parameterized. Harnesses call it once (or
|
||||||
|
// more, like the chapters harness's three bundles) and get back the loaded
|
||||||
|
// module plus a scoped cleanup function.
|
||||||
|
import esbuild from "esbuild";
|
||||||
|
import fs from "fs";
|
||||||
|
import os from "os";
|
||||||
|
import path from "path";
|
||||||
|
import url from "url";
|
||||||
|
|
||||||
|
export async function bundleForTest({
|
||||||
|
// Unique-ish name; also names the temp artifacts (and the generated entry
|
||||||
|
// file when entrySource is used).
|
||||||
|
name,
|
||||||
|
// Module paths to bundle directly (relative to the project root or absolute).
|
||||||
|
entryPoints,
|
||||||
|
// Alternative to entryPoints: inline TS re-export text, written to a temp
|
||||||
|
// entry file next to the project root (deleted right after the build).
|
||||||
|
entrySource,
|
||||||
|
format = "esm",
|
||||||
|
external = [],
|
||||||
|
} = {}) {
|
||||||
|
const ext = format === "cjs" ? "cjs" : "mjs";
|
||||||
|
const out = path.join(os.tmpdir(), `${name}-${process.pid}.${ext}`);
|
||||||
|
let tempEntry = null;
|
||||||
|
let eps = entryPoints ?? [];
|
||||||
|
if (entrySource !== undefined) {
|
||||||
|
tempEntry = path.resolve(`.${name}-entry.ts`);
|
||||||
|
fs.writeFileSync(tempEntry, entrySource);
|
||||||
|
eps = [tempEntry];
|
||||||
|
}
|
||||||
|
await esbuild.build({
|
||||||
|
entryPoints: eps.map((p) => path.resolve(p)),
|
||||||
|
bundle: true,
|
||||||
|
platform: "node",
|
||||||
|
format,
|
||||||
|
outfile: out,
|
||||||
|
external,
|
||||||
|
write: true,
|
||||||
|
logLevel: "silent",
|
||||||
|
});
|
||||||
|
if (tempEntry) fs.rmSync(tempEntry, { force: true });
|
||||||
|
const mod = await import(url.pathToFileURL(out).href);
|
||||||
|
return {
|
||||||
|
mod,
|
||||||
|
// Removes only this call's bundled artifact.
|
||||||
|
cleanupBundle() {
|
||||||
|
fs.rmSync(out, { force: true });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,34 +1,18 @@
|
||||||
// Standalone test for chapter CRUD logic.
|
// Standalone test for chapter CRUD logic.
|
||||||
// Run with: node tests/run-chapters-test.mjs
|
// Run with: node tests/run-chapters-test.mjs
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import url from "url";
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
|
|
||||||
const projOut = path.join(os.tmpdir(), `folio-project-${process.pid}.mjs`);
|
const { mod: project, cleanupBundle: cleanupProj } = await bundleForTest({
|
||||||
const chapOut = path.join(os.tmpdir(), `folio-chapters-${process.pid}.mjs`);
|
name: "folio-project",
|
||||||
await esbuild.build({
|
entryPoints: ["src/main/project.ts"],
|
||||||
entryPoints: [path.resolve("src/main/project.ts")],
|
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: projOut,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
await esbuild.build({
|
const { mod: chapters, cleanupBundle: cleanupChap } = await bundleForTest({
|
||||||
entryPoints: [path.resolve("src/main/chapters.ts")],
|
name: "folio-chapters",
|
||||||
bundle: true,
|
entryPoints: ["src/main/chapters.ts"],
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: chapOut,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const project = await import(url.pathToFileURL(projOut).href);
|
|
||||||
const chapters = await import(url.pathToFileURL(chapOut).href);
|
|
||||||
const { createBook, loadBook, saveMeta, hasBook } = project;
|
const { createBook, loadBook, saveMeta, hasBook } = project;
|
||||||
const {
|
const {
|
||||||
listChaptersInOrder,
|
listChaptersInOrder,
|
||||||
|
|
@ -145,18 +129,12 @@ ok(JSON.stringify(moveInOrder(["a", "b", "c", "d"], 3, 0)) === JSON.stringify(["
|
||||||
ok(JSON.stringify(moveInOrder(["a", "b", "c", "d"], 1, 1)) === JSON.stringify(["a", "b", "c", "d"]), "no-op on same index");
|
ok(JSON.stringify(moveInOrder(["a", "b", "c", "d"], 1, 1)) === JSON.stringify(["a", "b", "c", "d"]), "no-op on same index");
|
||||||
|
|
||||||
// ---- export (combineMarkdown + buildZip) ----
|
// ---- export (combineMarkdown + buildZip) ----
|
||||||
const exportOut = path.join(os.tmpdir(), `folio-export-${process.pid}.cjs`);
|
const { mod: exportMod, cleanupBundle: cleanupExport } = await bundleForTest({
|
||||||
await esbuild.build({
|
name: "folio-export",
|
||||||
entryPoints: [path.resolve("src/main/export.ts")],
|
entryPoints: ["src/main/export.ts"],
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
outfile: exportOut,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
const exportMod = (await import(url.pathToFileURL(exportOut).href)).default;
|
const { combineMarkdown, buildZip } = exportMod.default;
|
||||||
const { combineMarkdown, buildZip } = exportMod;
|
|
||||||
|
|
||||||
const b1 = createChapter(dir, "Intro");
|
const b1 = createChapter(dir, "Intro");
|
||||||
setChapterContent(dir, b1.id, "# Intro\n\nHello world\n\n- a\n- b");
|
setChapterContent(dir, b1.id, "# Intro\n\nHello world\n\n- a\n- b");
|
||||||
|
|
@ -177,10 +155,10 @@ ok(zip.includes("title_page.md"), "zip contains title_page.md");
|
||||||
ok(zip.includes("manifest.json"), "zip contains manifest.json");
|
ok(zip.includes("manifest.json"), "zip contains manifest.json");
|
||||||
ok(zip.includes("chapters"), "zip contains a chapters/ folder");
|
ok(zip.includes("chapters"), "zip contains a chapters/ folder");
|
||||||
ok(zip.slice(0, 2).toString("ascii") === "PK", "zip starts with PK signature");
|
ok(zip.slice(0, 2).toString("ascii") === "PK", "zip starts with PK signature");
|
||||||
fs.rmSync(exportOut, { force: true });
|
cleanupExport();
|
||||||
|
|
||||||
fs.rmSync(projOut, { force: true });
|
cleanupProj();
|
||||||
fs.rmSync(chapOut, { force: true });
|
cleanupChap();
|
||||||
fs.rmSync(dir, { recursive: true, force: true });
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
|
|
||||||
console.log("\nChapter tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
console.log("\nChapter tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
// Runner for the Tiptap editor test. Sets up a jsdom DOM, then dynamically
|
// Runner for the Tiptap editor test. Sets up a jsdom DOM, then dynamically
|
||||||
// imports the bundled editor module so Tiptap sees a browser-like environment.
|
// imports the bundled editor module so Tiptap sees a browser-like environment.
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import url from "url";
|
|
||||||
import { JSDOM } from "jsdom";
|
import { JSDOM } from "jsdom";
|
||||||
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
|
|
||||||
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
|
||||||
pretendToBeVisual: true,
|
pretendToBeVisual: true,
|
||||||
|
|
@ -24,19 +23,10 @@ g.DOMParser = window.DOMParser;
|
||||||
g.requestAnimationFrame = (cb) => setTimeout(cb, 0);
|
g.requestAnimationFrame = (cb) => setTimeout(cb, 0);
|
||||||
g.cancelAnimationFrame = (id) => clearTimeout(id);
|
g.cancelAnimationFrame = (id) => clearTimeout(id);
|
||||||
|
|
||||||
const out = path.join(os.tmpdir(), `folio-editor-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
const entry = path.resolve("tests/.folio-editor-test-entry.ts");
|
name: "folio-editor",
|
||||||
await esbuild.build({
|
entryPoints: ["tests/.folio-editor-test-entry.ts"],
|
||||||
entryPoints: [entry],
|
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
const {
|
const {
|
||||||
createTiptapEditor,
|
createTiptapEditor,
|
||||||
runCommand,
|
runCommand,
|
||||||
|
|
@ -235,7 +225,7 @@ ok(
|
||||||
"standalone Highlight button applies a default highlight to the selection"
|
"standalone Highlight button applies a default highlight to the selection"
|
||||||
);
|
);
|
||||||
|
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
fs.rmSync(book, { recursive: true, force: true });
|
fs.rmSync(book, { recursive: true, force: true });
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,10 @@
|
||||||
// renderer assembly + Tiptap modules, and verifies that a book assembled from
|
// renderer assembly + Tiptap modules, and verifies that a book assembled from
|
||||||
// native chapters renders with correct chapter order, page-break anchors,
|
// native chapters renders with correct chapter order, page-break anchors,
|
||||||
// reorder behavior, title injection, and Copy-All native fidelity.
|
// reorder behavior, title injection, and Copy-All native fidelity.
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import url from "url";
|
|
||||||
import { JSDOM } from "jsdom";
|
import { JSDOM } from "jsdom";
|
||||||
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
|
|
||||||
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
|
||||||
pretendToBeVisual: true,
|
pretendToBeVisual: true,
|
||||||
|
|
@ -26,19 +24,10 @@ g.DOMParser = window.DOMParser;
|
||||||
g.requestAnimationFrame = (cb) => setTimeout(cb, 0);
|
g.requestAnimationFrame = (cb) => setTimeout(cb, 0);
|
||||||
g.cancelAnimationFrame = (id) => clearTimeout(id);
|
g.cancelAnimationFrame = (id) => clearTimeout(id);
|
||||||
|
|
||||||
const out = path.join(os.tmpdir(), `folio-fullbook-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
const entry = path.resolve("tests/.folio-fullbook-test-entry.ts");
|
name: "folio-fullbook",
|
||||||
await esbuild.build({
|
entryPoints: ["tests/.folio-fullbook-test-entry.ts"],
|
||||||
entryPoints: [entry],
|
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
const {
|
const {
|
||||||
buildFullBookDoc,
|
buildFullBookDoc,
|
||||||
nativeNodeText,
|
nativeNodeText,
|
||||||
|
|
@ -190,6 +179,6 @@ ok(
|
||||||
"empty book assembles to empty doc"
|
"empty book assembles to empty doc"
|
||||||
);
|
);
|
||||||
|
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
console.log("\nFull Book tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
console.log("\nFull Book tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
||||||
process.exit(failures === 0 ? 0 : 1);
|
process.exit(failures === 0 ? 0 : 1);
|
||||||
|
|
|
||||||
|
|
@ -8,37 +8,22 @@
|
||||||
// - idempotency (original .md untouched)
|
// - idempotency (original .md untouched)
|
||||||
// Builds src/main/migration.ts with esbuild (no Electron needed).
|
// Builds src/main/migration.ts with esbuild (no Electron needed).
|
||||||
// Run with: node tests/run-migration-test.mjs
|
// Run with: node tests/run-migration-test.mjs
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import url from "url";
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
|
|
||||||
const out = path.join(os.tmpdir(), `folio-migration-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
const entry = path.resolve(".folio-mig-test-entry.ts");
|
name: "folio-migration",
|
||||||
fs.writeFileSync(
|
entrySource: `
|
||||||
entry,
|
|
||||||
`
|
|
||||||
export { migrateChapterToNative, migrateBookToNative, isNativeChapter } from "./src/main/migration.ts";
|
export { migrateChapterToNative, migrateBookToNative, isNativeChapter } from "./src/main/migration.ts";
|
||||||
export { createBook, loadBook, saveMeta } from "./src/main/project.ts";
|
export { createBook, loadBook, saveMeta } from "./src/main/project.ts";
|
||||||
export { setChapterContent, getChapterContent } from "./src/main/chapters.ts";
|
export { setChapterContent, getChapterContent } from "./src/main/chapters.ts";
|
||||||
export { markdownToNative } from "./src/main/markdown-to-native.ts";
|
export { markdownToNative } from "./src/main/markdown-to-native.ts";
|
||||||
export { parseChapter, serializeChapter, migrateDoc, getChapterDoc, nativeChapterFile, CURRENT_DOC_SCHEMA_VERSION, isValidDoc } from "./src/main/native-doc.ts";
|
export { parseChapter, serializeChapter, migrateDoc, getChapterDoc, nativeChapterFile, CURRENT_DOC_SCHEMA_VERSION, isValidDoc } from "./src/main/native-doc.ts";
|
||||||
export { getRecoveryRoot, _resetSessionBackupGuard } from "./src/main/backup.ts";
|
export { getRecoveryRoot, _resetSessionBackupGuard } from "./src/main/backup.ts";
|
||||||
`
|
`,
|
||||||
);
|
|
||||||
await esbuild.build({
|
|
||||||
entryPoints: [entry],
|
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
fs.rmSync(entry, { force: true });
|
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
const {
|
const {
|
||||||
createBook,
|
createBook,
|
||||||
setChapterContent,
|
setChapterContent,
|
||||||
|
|
@ -291,7 +276,7 @@ ok(
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Cleanup
|
// Cleanup
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
fs.rmSync(book, { recursive: true, force: true });
|
fs.rmSync(book, { recursive: true, force: true });
|
||||||
for (const d of backups) {
|
for (const d of backups) {
|
||||||
fs.rmSync(path.join(getRecoveryRoot(), d), { recursive: true, force: true });
|
fs.rmSync(path.join(getRecoveryRoot(), d), { recursive: true, force: true });
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,18 @@
|
||||||
// JSON, then inspects the produced ZIP contents to check that the manuscript,
|
// JSON, then inspects the produced ZIP contents to check that the manuscript,
|
||||||
// its chapter order, and its formatting survive the native -> DOCX path.
|
// its chapter order, and its formatting survive the native -> DOCX path.
|
||||||
// Run with: node tests/run-office-export-test.mjs
|
// Run with: node tests/run-office-export-test.mjs
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import url from "url";
|
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
|
|
||||||
const out = path.resolve(`tests/.tmp-folio-office-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
await esbuild.build({
|
name: "folio-office",
|
||||||
entryPoints: [path.resolve("src/main/office-export.ts")],
|
entryPoints: ["src/main/office-export.ts"],
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
external: ["electron"],
|
external: ["electron"],
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
|
|
||||||
let failures = 0;
|
let failures = 0;
|
||||||
const check = (name, ok) => {
|
const check = (name, ok) => {
|
||||||
console.log(`${ok ? "PASS" : "FAIL"} ${name}`);
|
console.log(`${ok ? "PASS" : "FAIL"} ${name}`);
|
||||||
|
|
@ -271,7 +262,7 @@ for (const [f, bytes] of origFiles) {
|
||||||
check("folio.json unchanged", fs.readFileSync(path.join(bookDir, "folio.json")).equals(origManifest));
|
check("folio.json unchanged", fs.readFileSync(path.join(bookDir, "folio.json")).equals(origManifest));
|
||||||
|
|
||||||
fs.rmSync(bookDir, { recursive: true, force: true });
|
fs.rmSync(bookDir, { recursive: true, force: true });
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
|
|
||||||
if (odtSkipped) {
|
if (odtSkipped) {
|
||||||
console.log("NOTE ODT verification requires LibreOffice; it was skipped.");
|
console.log("NOTE ODT verification requires LibreOffice; it was skipped.");
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,14 @@
|
||||||
// renderer module and verifies that chapter breaks become print sections and
|
// renderer module and verifies that chapter breaks become print sections and
|
||||||
// that every rich-text feature survives the native -> HTML conversion.
|
// that every rich-text feature survives the native -> HTML conversion.
|
||||||
// Run with: node tests/run-print-test.mjs
|
// Run with: node tests/run-print-test.mjs
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
import path from "path";
|
|
||||||
import url from "url";
|
|
||||||
|
|
||||||
const out = path.resolve(`tests/.tmp-folio-print-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
await esbuild.build({
|
name: "folio-print",
|
||||||
entryPoints: [path.resolve("src/renderer/print-format.ts")],
|
entryPoints: ["src/renderer/print-format.ts"],
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
external: ["electron"],
|
external: ["electron"],
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
const renderPrintChaptersNative = mod.renderPrintChaptersNative;
|
const renderPrintChaptersNative = mod.renderPrintChaptersNative;
|
||||||
|
|
||||||
let failures = 0;
|
let failures = 0;
|
||||||
|
|
@ -136,7 +125,7 @@ check("renders external link", /<a href="https:\/\/example.com">Site<\/a>/.test(
|
||||||
check("renders wikilink as internal anchor", /<a href="folio:chapter\/Two" class="wikilink internal">Go<\/a>/.test(html));
|
check("renders wikilink as internal anchor", /<a href="folio:chapter\/Two" class="wikilink internal">Go<\/a>/.test(html));
|
||||||
check("no raw wikilink brackets", !html.includes("[[Two"));
|
check("no raw wikilink brackets", !html.includes("[[Two"));
|
||||||
|
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
|
|
||||||
if (failures > 0) {
|
if (failures > 0) {
|
||||||
console.error(`\n${failures} check(s) failed.`);
|
console.error(`\n${failures} check(s) failed.`);
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,15 @@
|
||||||
// Standalone test for the pure project/recents logic.
|
// Standalone test for the pure project/recents logic.
|
||||||
// Builds src/main/project.ts with esbuild (no Electron needed) and asserts behavior.
|
// Builds src/main/project.ts with esbuild (no Electron needed) and asserts behavior.
|
||||||
// Run with: node tests/run-project-test.mjs
|
// Run with: node tests/run-project-test.mjs
|
||||||
import esbuild from "esbuild";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import url from "url";
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
|
|
||||||
const out = path.join(os.tmpdir(), `folio-project-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
await esbuild.build({
|
name: "folio-project",
|
||||||
entryPoints: [path.resolve("src/main/project.ts")],
|
entryPoints: ["src/main/project.ts"],
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
const {
|
const {
|
||||||
APP_ID,
|
APP_ID,
|
||||||
META_FILE,
|
META_FILE,
|
||||||
|
|
@ -78,7 +69,7 @@ const id = makeChapterId("Chapter One");
|
||||||
ok(id.startsWith("chapter-one-"), "chapter id slugified: " + id);
|
ok(id.startsWith("chapter-one-"), "chapter id slugified: " + id);
|
||||||
ok(chapterFileName(id) === `${id}.md`, "filename is <id>.md");
|
ok(chapterFileName(id) === `${id}.md`, "filename is <id>.md");
|
||||||
|
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
fs.rmSync(dir, { recursive: true, force: true });
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
|
|
||||||
console.log("\nProject tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
console.log("\nProject tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,13 @@
|
||||||
// Standalone test for the Obsidian-style wikilink plugin.
|
// Standalone test for the Obsidian-style wikilink plugin.
|
||||||
// Run with: node tests/run-wikilinks-test.mjs
|
// Run with: node tests/run-wikilinks-test.mjs
|
||||||
import esbuild from "esbuild";
|
|
||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from "markdown-it";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import os from "os";
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
||||||
import path from "path";
|
|
||||||
import url from "url";
|
|
||||||
|
|
||||||
const out = path.join(os.tmpdir(), `folio-wikilinks-${process.pid}.mjs`);
|
const { mod, cleanupBundle } = await bundleForTest({
|
||||||
await esbuild.build({
|
name: "folio-wikilinks",
|
||||||
entryPoints: [path.resolve("src/renderer/wikilinks.ts")],
|
entryPoints: ["src/renderer/wikilinks.ts"],
|
||||||
bundle: true,
|
|
||||||
platform: "node",
|
|
||||||
format: "esm",
|
|
||||||
outfile: out,
|
|
||||||
write: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(url.pathToFileURL(out).href);
|
|
||||||
const { wikilinkPlugin } = mod;
|
const { wikilinkPlugin } = mod;
|
||||||
|
|
||||||
const chapters = [
|
const chapters = [
|
||||||
|
|
@ -101,7 +90,7 @@ ok(!html8.includes('class="wikilink"'), "nested brackets not parsed as wikilink"
|
||||||
const html9 = md.render("empty [[] here");
|
const html9 = md.render("empty [[] here");
|
||||||
ok(!html9.includes('class="wikilink"'), "empty wikilink target not parsed");
|
ok(!html9.includes('class="wikilink"'), "empty wikilink target not parsed");
|
||||||
|
|
||||||
fs.rmSync(out, { force: true });
|
cleanupBundle();
|
||||||
|
|
||||||
console.log("\nWikilink tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
console.log("\nWikilink tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
||||||
process.exit(failures === 0 ? 0 : 1);
|
process.exit(failures === 0 ? 0 : 1);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue