chore(testing): Phase 9 — bun:test suite + CI gating with no-DB fakes
CI / typecheck + build (turbo) (push) Canceled after 0s

Added a real test suite (32 tests, 0 external services) using bun:test with
in-process module mocking for @mcpedia/db, @mcpedia/queue, @mcpedia/core.

Enablers:
- apps/api: extracted createApp(deps?) factory + dashboard.ts module from
  index.ts so the HTTP surface is unit-testable (real queue is lazy-imported).
- packages/core: exported shouldCreateRevision pure predicate; restoreRevision
  gained an opts.reindex seam for the chunk-rebuild contract.
- apps/mcp: renamed smoke.test.ts -> smoke.ts (bun test now owns .test.ts),
  updated stale assertions (10 tools, 4 docs in docs section).
- infra: turbo test task (cache:false), test scripts across packages,
  @types/bun + tsconfig base types, CI 'Test' step after Build.

Packages with tests: embeddings(5), parser(5), search(8), core(4),
mcp(6 auth-gates), api(8 contracts).

All green: typecheck(4/4), test(6/6 pkgs), build(web). Live API verified
/health, /metrics, /dashboard, /hooks/* auth gate on temp port.
This commit is contained in:
asepharyana
2026-08-20 11:12:32 +07:00
parent 0cdf261d40
commit 76f778c10d
25 changed files with 1055 additions and 193 deletions
+81
View File
@@ -0,0 +1,81 @@
import { test, expect, afterEach, beforeEach } from "bun:test";
// parseFile uses node:fs, so we test it by writing a temp file. This keeps the
// parser package dependency-free while still exercising gray-matter.
import { parseFile } from "../src/index";
import { writeFileSync, mkdtempSync, rmSync, mkdirSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
let tmp: string;
beforeEach(() => {
tmp = mkdtempSync(join(tmpdir(), "mcpedia-parser-"));
});
afterEach(() => {
rmSync(tmp, { recursive: true, force: true });
});
function writeDoc(rel: string, frontmatter: string) {
const p = join(tmp, rel);
// Ensure the parent directory exists (sections like docs/, writeups/).
mkdirSync(join(p, ".."), { recursive: true });
writeFileSync(p, frontmatter, "utf8");
return parseFile(p, rel);
}
test("parseFile: extracts basic frontmatter", () => {
const { meta, body } = writeDoc(
"docs/test.md",
[
"---",
'id: test-doc',
'title: Test Document',
'type: documentation',
'tags: ["docs", "test"]',
'status: published',
'author: asep',
'created_at: 2026-08-19',
'updated_at: 2026-08-19',
"---",
"",
"# Hello",
"Body text here.",
].join("\n"),
);
expect(meta.slug).toBe("docs/test");
expect(meta.section).toBe("docs");
expect(meta.title).toBe("Test Document");
expect(meta.type).toBe("documentation");
expect(meta.status).toBe("published");
expect(meta.author).toBe("asep");
expect(meta.tags).toEqual(["docs", "test"]);
expect(body).toContain("# Hello");
});
test("parseFile: section derived from top-level dir", () => {
expect(writeDoc("writeups/foo.md", "---\ntitle: A\n---\nbody").meta.section).toBe("writeups");
expect(writeDoc("research/bar.md", "---\ntitle: B\n---\nbody").meta.section).toBe("research");
expect(writeDoc("notes/baz.md", "---\ntitle: C\n---\nbody").meta.section).toBe("notes");
});
test("parseFile: invalid type/status fall back to defaults", () => {
const { meta } = writeDoc(
"docs/x.md",
"---\ntitle: X\ntype: bogus\nstatus: bogus\n---\n",
);
expect(meta.type).toBe("documentation");
expect(meta.status).toBe("published");
});
test("parseFile: missing optional fields get sane defaults", () => {
const { meta } = writeDoc("docs/x.md", "---\ntitle: Just A Title\n---\n");
expect(meta.author).toBe("");
expect(meta.tags).toEqual([]);
expect(meta.createdAt).toBeTruthy();
expect(meta.updatedAt).toBeTruthy();
});
test("parseFile: body excludes frontmatter delimiter", () => {
const { body } = writeDoc("docs/x.md", "---\ntitle: T\n---\n# Real body\n\nParagraph.");
expect(body).not.toContain("---");
expect(body).toContain("# Real body");
});