init
This commit is contained in:
commit
932d4ad420
46 changed files with 5800 additions and 0 deletions
205
tests/lib/tracker.test.ts
Normal file
205
tests/lib/tracker.test.ts
Normal 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)
|
||||
}
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue