syntaxai/tdd.md · main · src / a31_admin_validation.test.ts

a31_admin_validation.test.ts 214 lines · 4875 bytes raw
import { test, expect } from "bun:test";
import {
  validateEditForm,
  MAX_ADMIN_HTML_BYTES,
} from "./a31_admin_validation.ts";

test("accepts a minimally valid form", () => {
  const r = validateEditForm({
    slug: "hello",
    type: "page",
    title: "Hello",
    html: "<p>x</p>",
    status: "published",
  });
  expect(r.ok).toBe(true);
  if (r.ok) {
    expect(r.data.slug).toBe("hello");
    expect(r.data.type).toBe("page");
    expect(r.data.primaryTag).toBeNull();
  }
});

test("lowercases the slug and trims surrounding whitespace", () => {
  const r = validateEditForm({
    slug: "  HELLO-World ",
    type: "post",
    title: "X",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.slug).toBe("hello-world");
});

test("rejects missing title", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "page",
    title: "   ",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/title/i);
});

test("rejects slug with uppercase letters", () => {
  const r = validateEditForm({
    slug: "NotOK",
    type: "page",
    title: "T",
    html: "<p>x</p>",
  });
  // lowercased to "notok" by the trimmer — that should pass.
  expect(r.ok).toBe(true);
});

test("accepts multi-segment slug with single-slash separators", () => {
  const r = validateEditForm({
    slug: "company/about",
    type: "page",
    title: "About",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.slug).toBe("company/about");
});

test("accepts deeply nested multi-segment slug", () => {
  const r = validateEditForm({
    slug: "docs/spec/grammar",
    type: "page",
    title: "Grammar",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.slug).toBe("docs/spec/grammar");
});

test("trims leading and trailing slashes from slug", () => {
  const r = validateEditForm({
    slug: "/foo/bar/",
    type: "page",
    title: "T",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.slug).toBe("foo/bar");
});

test("rejects slug with consecutive slashes", () => {
  const r = validateEditForm({
    slug: "a//b",
    type: "page",
    title: "T",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/slug/i);
});

test("rejects empty segment after trim", () => {
  const r = validateEditForm({
    slug: "//",
    type: "page",
    title: "T",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/slug/i);
});

test("rejects slug containing whitespace", () => {
  const r = validateEditForm({
    slug: "two words",
    type: "page",
    title: "T",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/slug/i);
});

test("rejects unknown type", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "snippet",
    title: "X",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/type/i);
});

test("rejects unknown status", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "page",
    title: "X",
    html: "<p>x</p>",
    status: "deferred",
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/status/i);
});

test("defaults status to published when omitted", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "page",
    title: "X",
    html: "<p>x</p>",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.status).toBe("published");
});

test("accepts draft status", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "page",
    title: "X",
    html: "<p>x</p>",
    status: "draft",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.status).toBe("draft");
});

test("captures primary_tag when non-empty", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "post",
    title: "P",
    html: "<p>x</p>",
    primary_tag: "concept",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.primaryTag).toBe("concept");
});

test("treats blank primary_tag as null", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "post",
    title: "P",
    html: "<p>x</p>",
    primary_tag: "   ",
  });
  expect(r.ok).toBe(true);
  if (r.ok) expect(r.data.primaryTag).toBeNull();
});

test("rejects html body over the size cap", () => {
  // Build a 1 MB + 1 byte payload of single-byte chars.
  const big = "a".repeat(MAX_ADMIN_HTML_BYTES + 1);
  const r = validateEditForm({
    slug: "ok",
    type: "page",
    title: "X",
    html: big,
  });
  expect(r.ok).toBe(false);
  if (!r.ok) expect(r.error).toMatch(/limit/i);
});

test("accepts empty html body (parser handles it as an empty doc)", () => {
  const r = validateEditForm({
    slug: "ok",
    type: "page",
    title: "X",
    html: "",
  });
  expect(r.ok).toBe(true);
});