This commit is contained in:
Tiara Rodney 2026-03-15 03:02:41 +01:00
commit 932d4ad420
No known key found for this signature in database
GPG key ID: 5CD8EC1D46106723
46 changed files with 5800 additions and 0 deletions

205
tests/lib/tracker.test.ts Normal file
View file

@ -0,0 +1,205 @@
import * as fs from "fs"
import { describe, it, expect } from "vitest"
import { parseModules, parseBugzillaTracker } from "../../lib/tracker"
import { parseTodoFile } from "../../lib/file"
import { serializeTodoFile, serializeModules, serializeBugzillaTracker } from "../../lib/serializer"
describe("parseModules", () => {
it("parses modules list", () => {
const text = `Modules:
- Name: General
Path: .
- Name: Frontend
Path: src/frontend`
const modules = parseModules(text)
expect(modules).toHaveLength(2)
expect(modules[0]).toEqual({ name: "General", path: "." })
expect(modules[1]).toEqual({ name: "Frontend", path: "src/frontend" })
})
})
describe("parseBugzillaTracker", () => {
it("parses bugzilla tracker with mappings", () => {
const text = `URL: https://bugzilla.example.com
Mappings:
- Module: General
Product: MyProject
Component: General
- Module: Frontend
Product: MyProject
Component: FrontendUI`
const tracker = parseBugzillaTracker(text)
expect(tracker.url).toBe("https://bugzilla.example.com")
expect(tracker.mappings).toHaveLength(2)
expect(tracker.mappings[0]).toEqual({
module: "General",
product: "MyProject",
component: "General",
})
expect(tracker.mappings[1]).toEqual({
module: "Frontend",
product: "MyProject",
component: "FrontendUI",
})
})
})
describe("parseTodoFile with modules and bugzilla", () => {
it("parses TODO with modules and bugzilla parts", async () => {
const todo = await parseTodoFile("tests/_mocks/todo-with-tracker.txt")
expect(todo.modules).toBeDefined()
expect(todo.modules).toHaveLength(3)
expect(todo.modules![0].name).toBe("General")
expect(todo.bugzilla).toBeDefined()
expect(todo.bugzilla!.url).toBe("https://bugzilla.example.com")
expect(todo.bugzilla!.mappings).toHaveLength(3)
expect(todo.issues).toHaveLength(2)
expect(todo.issues[0].module).toBe("Frontend")
expect(todo.issues[1].module).toBe("Backend")
})
it("rejects issue with invalid module", async () => {
const raw = `--ISSUE
Content-Type: application/modules
Modules:
- Name: General
Path: .
--ISSUE
Content-Type: application/issue
ID: 1
Type: feature
Title: Bad module
Status: open
Priority: low
Created: 2026-01-01
Module: NonExistent
Relationships:
Description: Test`
const tmpPath = "tests/_mocks/_bad-module.txt"
fs.writeFileSync(tmpPath, raw)
try {
await expect(parseTodoFile(tmpPath)).rejects.toThrow("NonExistent")
} finally {
fs.unlinkSync(tmpPath)
}
})
it("rejects bugzilla mapping referencing undefined module", async () => {
const raw = `--ISSUE
Content-Type: application/modules
Modules:
- Name: General
Path: .
--ISSUE
Content-Type: application/bugzilla
URL: https://bz.example.com
Mappings:
- Module: DoesNotExist
Product: P
Component: C
--ISSUE
Content-Type: application/issue
ID: 1
Type: feature
Title: Test
Status: open
Priority: low
Created: 2026-01-01
Relationships:
Description: Test`
const tmpPath = "tests/_mocks/_bad-bz-mapping.txt"
fs.writeFileSync(tmpPath, raw)
try {
await expect(parseTodoFile(tmpPath)).rejects.toThrow("DoesNotExist")
} finally {
fs.unlinkSync(tmpPath)
}
})
it("rejects dangling relationship targets", async () => {
const raw = `--ISSUE
Content-Type: application/issue
ID: 1
Type: feature
Title: Test
Status: open
Priority: low
Created: 2026-01-01
Relationships: dependsOn:99
Description: Test`
const tmpPath = "tests/_mocks/_bad-rel.txt"
fs.writeFileSync(tmpPath, raw)
try {
await expect(parseTodoFile(tmpPath)).rejects.toThrow("#99")
} finally {
fs.unlinkSync(tmpPath)
}
})
})
describe("serialize modules and bugzilla", () => {
it("serializes modules part", () => {
const result = serializeModules([
{ name: "General", path: "." },
{ name: "Frontend", path: "src/frontend" },
])
expect(result).toContain("Modules:")
expect(result).toContain("- Name: General")
expect(result).toContain("Path: .")
expect(result).toContain("- Name: Frontend")
})
it("serializes bugzilla tracker part", () => {
const result = serializeBugzillaTracker({
url: "https://bugzilla.example.com",
mappings: [
{ module: "General", product: "MyProject", component: "General" },
],
})
expect(result).toContain("URL: https://bugzilla.example.com")
expect(result).toContain("- Module: General")
expect(result).toContain("Product: MyProject")
expect(result).toContain("Component: General")
})
})
describe("round-trip with modules and bugzilla", () => {
it("parse → serialize → parse preserves modules, bugzilla, and issue modules", async () => {
const todo1 = await parseTodoFile("tests/_mocks/todo-with-tracker.txt")
const serialized = serializeTodoFile(todo1)
const tmpPath = "tests/_mocks/_roundtrip-tracker.txt"
fs.writeFileSync(tmpPath, serialized)
try {
const todo2 = await parseTodoFile(tmpPath)
expect(todo2.modules).toHaveLength(todo1.modules!.length)
for (let i = 0; i < todo1.modules!.length; i++) {
expect(todo2.modules![i]).toEqual(todo1.modules![i])
}
expect(todo2.bugzilla!.url).toBe(todo1.bugzilla!.url)
expect(todo2.bugzilla!.mappings).toHaveLength(todo1.bugzilla!.mappings.length)
for (let i = 0; i < todo1.bugzilla!.mappings.length; i++) {
expect(todo2.bugzilla!.mappings[i]).toEqual(todo1.bugzilla!.mappings[i])
}
for (let i = 0; i < todo1.issues.length; i++) {
expect(todo2.issues[i].module).toBe(todo1.issues[i].module)
}
} finally {
fs.unlinkSync(tmpPath)
}
})
})