SPB Git
2.6 KB · 31 lines typescript
1import { describe, it, expect } from "vitest";2import { readFileSync } from "node:fs";3import { qualityScore } from "@/lib/quality";4import { toolRecordSchema, WORD } from "@/lib/content/schema";5import { renderMarkdown, slugify } from "@/lib/text";6const duck = JSON.parse(readFileSync("content/tools/duckdb.json", "utf8"));7describe("content schema", () => {8  it("accepts the reference record", () => { expect(toolRecordSchema.safeParse(duck).success).toBe(true); });9  it("rejects bad slugs, schemes, enums and short summaries", () => {10    expect(toolRecordSchema.safeParse({ ...duck, slug: "Duck DB" }).success).toBe(false);11    expect(toolRecordSchema.safeParse({ ...duck, homepage_url: "ftp://x.org" }).success).toBe(false);12    expect(toolRecordSchema.safeParse({ ...duck, source_model: "freeware" }).success).toBe(false);13    expect(toolRecordSchema.safeParse({ ...duck, summary: "too short" }).success).toBe(false);14    expect(toolRecordSchema.safeParse({ ...duck, sources: [] }).success).toBe(false);15  });16  it("defaults visibility public and status reviewed", () => { const r = toolRecordSchema.parse({ ...duck, visibility: undefined, editorial_status: undefined }); expect(r.visibility).toBe("public"); expect(r.editorial_status).toBe("reviewed"); });17});18describe("quality score", () => {19  const p = toolRecordSchema.parse(duck);20  it("is deterministic, bounded and rewards evidence/link state", () => {21    const a = qualityScore(p, "unchecked"), b = qualityScore(p, "ok"), c = qualityScore(p, "broken");22    expect(a).toBe(qualityScore(p, "unchecked")); expect(b).toBeGreaterThan(a); expect(c).toBeLessThan(a); expect(b).toBeLessThanOrEqual(100); expect(c).toBeGreaterThanOrEqual(0);23  });24  it("penalizes thin records", () => { const thin = { ...p, description: "x ".repeat(60), capabilities: ["a", "b"], limitations: [], workflows: [], advantages: [], alternatives: [], tags: [], use_cases: [], docs_url: undefined, repo_url: undefined, license_spdx: undefined, sources: p.sources.slice(0, 1), confidence: "low" as const, comparison_notes: undefined }; expect(qualityScore(thin)).toBeLessThan(40); });25  it("WORD counts words", () => { expect(WORD(" a  b\nc ")).toBe(3); });26});27describe("text", () => {28  it("renderMarkdown strips scripts and adds rel noopener", () => { const h = renderMarkdown("Hi <script>alert(1)</script> [x](https://a.com) <img src=x onerror=alert(1)>"); expect(h).not.toContain("<script"); expect(h).not.toContain("onerror"); expect(h).toContain('rel="noopener noreferrer nofollow"'); });29  it("slugify", () => { expect(slugify("Éléphant & Co.")).toBe("elephant-co"); });30});31
Files · 19c0ff748ee94e0979c734f5fb3afeefc11ee9e1
Menu

Theme