129 lines
4.2 KiB
TypeScript
129 lines
4.2 KiB
TypeScript
import * as fs from "fs"
|
|
import { describe, it, expect } from "vitest"
|
|
import { parseTodoFile } from "../../src/file.js"
|
|
import {
|
|
serializeTodoFile,
|
|
serializeIssue,
|
|
serializeSprints,
|
|
serializeRelationships,
|
|
} from "../../src/serializer.js"
|
|
|
|
describe("serializeRelationships", () => {
|
|
it("serializes empty relationships", () => {
|
|
expect(serializeRelationships({})).toBe("")
|
|
})
|
|
|
|
it("serializes single relationship", () => {
|
|
expect(serializeRelationships({ dependsOn: [3] })).toBe("dependsOn:3")
|
|
})
|
|
|
|
it("serializes multiple relationships", () => {
|
|
const result = serializeRelationships({ dependsOn: [3, 4], blocks: [7] })
|
|
expect(result).toContain("dependsOn:3 4")
|
|
expect(result).toContain("blocks:7")
|
|
})
|
|
})
|
|
|
|
describe("serializeSprints", () => {
|
|
it("serializes empty sprints", () => {
|
|
expect(serializeSprints([])).toBe("Sprints:")
|
|
})
|
|
|
|
it("serializes sprint list", () => {
|
|
const result = serializeSprints([
|
|
{ name: "Alpha", start: "2026-02-01", end: "2026-02-14" },
|
|
])
|
|
expect(result).toContain("Sprints:")
|
|
expect(result).toContain("- Name: Alpha")
|
|
expect(result).toContain("Range: 2026-02-01..2026-02-14")
|
|
})
|
|
})
|
|
|
|
describe("serializeIssue", () => {
|
|
it("serializes an issue with all fields", () => {
|
|
const result = serializeIssue({
|
|
id: 1,
|
|
type: "feature",
|
|
title: "Test",
|
|
status: "open",
|
|
priority: "high",
|
|
created: "2026-02-05",
|
|
relationships: { dependsOn: [3] },
|
|
description: "A test issue",
|
|
body: "",
|
|
})
|
|
expect(result).toContain("ID: 1")
|
|
expect(result).toContain("Type: feature")
|
|
expect(result).toContain("Title: Test")
|
|
expect(result).toContain("Status: open")
|
|
expect(result).toContain("Priority: high")
|
|
expect(result).toContain("Created: 2026-02-05")
|
|
expect(result).toContain("Relationships: dependsOn:3")
|
|
expect(result).toContain("Description: A test issue")
|
|
})
|
|
|
|
it("serializes multi-line description", () => {
|
|
const result = serializeIssue({
|
|
id: 1,
|
|
type: "feature",
|
|
title: "Test",
|
|
status: "open",
|
|
priority: "high",
|
|
created: "2026-02-05",
|
|
relationships: {},
|
|
description: "Line one\nLine two",
|
|
body: "",
|
|
})
|
|
expect(result).toContain("Description: Line one")
|
|
expect(result).toContain(" Line two")
|
|
})
|
|
})
|
|
|
|
describe("round-trip", () => {
|
|
it("parse → serialize → parse produces equivalent data", async () => {
|
|
const todo1 = await parseTodoFile("tests/_mocks/todo-basic.txt")
|
|
const serialized = serializeTodoFile(todo1)
|
|
// Write to temp location for re-parsing
|
|
const tmpPath = "tests/_mocks/_roundtrip.txt"
|
|
fs.writeFileSync(tmpPath, serialized)
|
|
|
|
try {
|
|
const todo2 = await parseTodoFile(tmpPath)
|
|
expect(todo2.sprints.length).toBe(todo1.sprints.length)
|
|
expect(todo2.issues.length).toBe(todo1.issues.length)
|
|
|
|
for (let i = 0; i < todo1.sprints.length; i++) {
|
|
expect(todo2.sprints[i].name).toBe(todo1.sprints[i].name)
|
|
expect(todo2.sprints[i].start).toBe(todo1.sprints[i].start)
|
|
expect(todo2.sprints[i].end).toBe(todo1.sprints[i].end)
|
|
}
|
|
|
|
for (let i = 0; i < todo1.issues.length; i++) {
|
|
expect(todo2.issues[i].id).toBe(todo1.issues[i].id)
|
|
expect(todo2.issues[i].type).toBe(todo1.issues[i].type)
|
|
expect(todo2.issues[i].title).toBe(todo1.issues[i].title)
|
|
expect(todo2.issues[i].status).toBe(todo1.issues[i].status)
|
|
expect(todo2.issues[i].priority).toBe(todo1.issues[i].priority)
|
|
expect(todo2.issues[i].created).toBe(todo1.issues[i].created)
|
|
expect(todo2.issues[i].description).toBe(todo1.issues[i].description)
|
|
}
|
|
} finally {
|
|
fs.unlinkSync(tmpPath)
|
|
}
|
|
})
|
|
|
|
it("round-trips issues-only file", async () => {
|
|
const todo1 = await parseTodoFile("tests/_mocks/todo-issues-only.txt")
|
|
const serialized = serializeTodoFile(todo1)
|
|
const tmpPath = "tests/_mocks/_roundtrip2.txt"
|
|
fs.writeFileSync(tmpPath, serialized)
|
|
|
|
try {
|
|
const todo2 = await parseTodoFile(tmpPath)
|
|
expect(todo2.issues.length).toBe(todo1.issues.length)
|
|
expect(todo2.sprints.length).toBe(0)
|
|
} finally {
|
|
fs.unlinkSync(tmpPath)
|
|
}
|
|
})
|
|
})
|