schema.test.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { describe, it, expect, beforeAll } from "vitest"
  2. import Database from "better-sqlite3"
  3. import { SCHEMA_SQL } from "./schema"
  4. let db: Database.Database
  5. beforeAll(() => {
  6. db = new Database(":memory:")
  7. db.exec(SCHEMA_SQL)
  8. })
  9. describe("schema integrity", () => {
  10. it("creates pages table", () => {
  11. const result = db.prepare(
  12. "SELECT name FROM sqlite_master WHERE type='table' AND name='pages'",
  13. ).get() as { name: string } | undefined
  14. expect(result?.name).toBe("pages")
  15. })
  16. it("creates blocks table", () => {
  17. const result = db.prepare(
  18. "SELECT name FROM sqlite_master WHERE type='table' AND name='blocks'",
  19. ).get() as { name: string } | undefined
  20. expect(result?.name).toBe("blocks")
  21. })
  22. it("creates links table", () => {
  23. const result = db.prepare(
  24. "SELECT name FROM sqlite_master WHERE type='table' AND name='links'",
  25. ).get() as { name: string } | undefined
  26. expect(result?.name).toBe("links")
  27. })
  28. it("creates blocks_fts virtual table", () => {
  29. const result = db.prepare(
  30. "SELECT name FROM sqlite_master WHERE type='table' AND name='blocks_fts'",
  31. ).get() as { name: string } | undefined
  32. expect(result?.name).toBe("blocks_fts")
  33. })
  34. it("enforces pages.path primary key", () => {
  35. db.prepare("INSERT INTO pages (path, title, modified_at) VALUES ('a.md', 'A', 1000)").run()
  36. expect(() => {
  37. db.prepare("INSERT INTO pages (path, title, modified_at) VALUES ('a.md', 'A2', 2000)").run()
  38. }).toThrow()
  39. })
  40. it("creates all expected indices", () => {
  41. const indices = db.prepare(
  42. "SELECT name FROM sqlite_master WHERE type='index' AND name LIKE 'idx_%'",
  43. ).all() as { name: string }[]
  44. const names = indices.map((i) => i.name).sort()
  45. expect(names).toContain("idx_blocks_page")
  46. expect(names).toContain("idx_links_target")
  47. expect(names).toContain("idx_links_source")
  48. expect(names).toContain("idx_links_tag")
  49. })
  50. it("enforces link_type CHECK constraint", () => {
  51. db.prepare(
  52. "INSERT INTO pages (path, title, modified_at) VALUES ('p.md', 'P', 1000)",
  53. ).run()
  54. db.prepare(
  55. "INSERT INTO blocks (id, page_path, content, modified_at) VALUES ('b1', 'p.md', 'c', 1000)",
  56. ).run()
  57. expect(() => {
  58. db.prepare(
  59. "INSERT INTO links (source_block_id, source_page_path, target, link_type) VALUES ('b1', 'p.md', 'x', 'invalid-type')",
  60. ).run()
  61. }).toThrow()
  62. })
  63. it("enforces blocks.block_type CHECK constraint", () => {
  64. expect(() => {
  65. db.prepare(
  66. "INSERT INTO blocks (id, page_path, block_type, modified_at) VALUES ('b2', 'p.md', 'invalid-type', 1000)",
  67. ).run()
  68. }).toThrow()
  69. })
  70. })