274 lines
7.8 KiB
TypeScript
274 lines
7.8 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import {
|
|
alignAcceptanceCriteria,
|
|
CHECKBOX_PATTERNS,
|
|
type ChecklistItem,
|
|
extractAndFormatAcceptanceCriteria,
|
|
formatChecklist,
|
|
formatChecklistItem,
|
|
parseCheckboxLine,
|
|
parseCheckboxLines,
|
|
} from "../ui/checklist.ts";
|
|
|
|
describe("Checklist utilities", () => {
|
|
describe("CHECKBOX_PATTERNS", () => {
|
|
test("should match checked checkbox lines", () => {
|
|
const testCases = [
|
|
"- [x] Checked item",
|
|
" - [x] Indented checked item",
|
|
"- [x] Item with extra spaces",
|
|
"-[x] No space after dash",
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_LINE.test(testCase)).toBe(true);
|
|
}
|
|
});
|
|
|
|
test("should match unchecked checkbox lines", () => {
|
|
const testCases = [
|
|
"- [ ] Unchecked item",
|
|
" - [ ] Indented unchecked item",
|
|
"- [ ] Item with extra spaces",
|
|
"-[ ] No space after dash",
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_LINE.test(testCase)).toBe(true);
|
|
}
|
|
});
|
|
|
|
test("should not match non-checkbox lines", () => {
|
|
const testCases = [
|
|
"Regular text",
|
|
"- Regular bullet point",
|
|
"- [ Missing closing bracket",
|
|
"- [y] Invalid checkbox state",
|
|
"[x] Missing dash prefix",
|
|
"## Header",
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_LINE.test(testCase)).toBe(false);
|
|
}
|
|
});
|
|
|
|
test("should match checkbox prefix pattern", () => {
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_PREFIX.test("- [x] ")).toBe(true);
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_PREFIX.test("- [ ] ")).toBe(true);
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_PREFIX.test("-[x] ")).toBe(true);
|
|
expect(CHECKBOX_PATTERNS.CHECKBOX_PREFIX.test("- [x]")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("parseCheckboxLine", () => {
|
|
test("should parse checked checkbox lines", () => {
|
|
const result = parseCheckboxLine("- [x] This is checked");
|
|
expect(result).toEqual({
|
|
text: "This is checked",
|
|
checked: true,
|
|
});
|
|
});
|
|
|
|
test("should parse unchecked checkbox lines", () => {
|
|
const result = parseCheckboxLine("- [ ] This is unchecked");
|
|
expect(result).toEqual({
|
|
text: "This is unchecked",
|
|
checked: false,
|
|
});
|
|
});
|
|
|
|
test("should handle indented checkboxes", () => {
|
|
const result = parseCheckboxLine(" - [x] Indented checkbox");
|
|
expect(result).toEqual({
|
|
text: "Indented checkbox",
|
|
checked: true,
|
|
});
|
|
});
|
|
|
|
test("should handle extra whitespace", () => {
|
|
const result = parseCheckboxLine("- [x] Extra spaces around text ");
|
|
expect(result).toEqual({
|
|
text: "Extra spaces around text",
|
|
checked: true,
|
|
});
|
|
});
|
|
|
|
test("should return null for non-checkbox lines", () => {
|
|
expect(parseCheckboxLine("Regular text")).toBe(null);
|
|
expect(parseCheckboxLine("- Regular bullet")).toBe(null);
|
|
expect(parseCheckboxLine("## Header")).toBe(null);
|
|
});
|
|
});
|
|
|
|
describe("formatChecklistItem", () => {
|
|
test("should format checked item with default options", () => {
|
|
const item: ChecklistItem = { text: "Test item", checked: true };
|
|
const result = formatChecklistItem(item);
|
|
expect(result).toBe(" [x] Test item");
|
|
});
|
|
|
|
test("should format unchecked item with default options", () => {
|
|
const item: ChecklistItem = { text: "Test item", checked: false };
|
|
const result = formatChecklistItem(item);
|
|
expect(result).toBe(" [ ] Test item");
|
|
});
|
|
|
|
test("should use custom symbols", () => {
|
|
const item: ChecklistItem = { text: "Test item", checked: true };
|
|
const result = formatChecklistItem(item, {
|
|
checkedSymbol: "☑",
|
|
uncheckedSymbol: "☐",
|
|
});
|
|
expect(result).toBe(" ☑ Test item");
|
|
});
|
|
|
|
test("should use custom padding", () => {
|
|
const item: ChecklistItem = { text: "Test item", checked: false };
|
|
const result = formatChecklistItem(item, {
|
|
padding: " ",
|
|
});
|
|
expect(result).toBe(" [ ] Test item");
|
|
});
|
|
});
|
|
|
|
describe("parseCheckboxLines", () => {
|
|
test("should parse multiple checkbox lines", () => {
|
|
const text = `- [x] First item
|
|
- [ ] Second item
|
|
- [x] Third item`;
|
|
|
|
const result = parseCheckboxLines(text);
|
|
expect(result).toEqual([
|
|
{ text: "First item", checked: true },
|
|
{ text: "Second item", checked: false },
|
|
{ text: "Third item", checked: true },
|
|
]);
|
|
});
|
|
|
|
test("should ignore non-checkbox lines", () => {
|
|
const text = `- [x] Checkbox item
|
|
Regular text
|
|
- [ ] Another checkbox
|
|
## Header`;
|
|
|
|
const result = parseCheckboxLines(text);
|
|
expect(result).toEqual([
|
|
{ text: "Checkbox item", checked: true },
|
|
{ text: "Another checkbox", checked: false },
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("formatChecklist", () => {
|
|
test("should format multiple items consistently", () => {
|
|
const items: ChecklistItem[] = [
|
|
{ text: "First item", checked: true },
|
|
{ text: "Second item", checked: false },
|
|
{ text: "Third item", checked: true },
|
|
];
|
|
|
|
const result = formatChecklist(items);
|
|
expect(result).toEqual([" [x] First item", " [ ] Second item", " [x] Third item"]);
|
|
});
|
|
});
|
|
|
|
describe("alignAcceptanceCriteria", () => {
|
|
test("should align checkbox items consistently", () => {
|
|
const criteriaSection = `- [x] First criterion
|
|
- [ ] Second criterion
|
|
- [x] Third criterion`;
|
|
|
|
const result = alignAcceptanceCriteria(criteriaSection);
|
|
expect(result).toEqual([" [x] First criterion", " [ ] Second criterion", " [x] Third criterion"]);
|
|
});
|
|
|
|
test("should handle mixed content with consistent padding", () => {
|
|
const criteriaSection = `- [x] Checkbox item
|
|
Regular note
|
|
- [ ] Another checkbox`;
|
|
|
|
const result = alignAcceptanceCriteria(criteriaSection);
|
|
expect(result).toEqual([" [x] Checkbox item", " Regular note", " [ ] Another checkbox"]);
|
|
});
|
|
|
|
test("should handle empty or whitespace-only lines", () => {
|
|
const criteriaSection = `- [x] First item
|
|
|
|
- [ ] Second item
|
|
|
|
- [x] Third item`;
|
|
|
|
const result = alignAcceptanceCriteria(criteriaSection);
|
|
expect(result).toEqual([" [x] First item", " [ ] Second item", " [x] Third item"]);
|
|
});
|
|
});
|
|
|
|
describe("extractAndFormatAcceptanceCriteria", () => {
|
|
test("should extract and format acceptance criteria from markdown", () => {
|
|
const content = `## Description
|
|
Some description here.
|
|
|
|
## Acceptance Criteria
|
|
- [x] First criterion is done
|
|
- [ ] Second criterion pending
|
|
- [x] Third criterion complete
|
|
|
|
## Implementation Notes
|
|
Some notes here.`;
|
|
|
|
const result = extractAndFormatAcceptanceCriteria(content);
|
|
expect(result).toEqual([
|
|
" [x] First criterion is done",
|
|
" [ ] Second criterion pending",
|
|
" [x] Third criterion complete",
|
|
]);
|
|
});
|
|
|
|
test("should return empty array when no acceptance criteria section exists", () => {
|
|
const content = `## Description
|
|
Some description here.
|
|
|
|
## Implementation Notes
|
|
Some notes here.`;
|
|
|
|
const result = extractAndFormatAcceptanceCriteria(content);
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
test("should handle case-insensitive section headers", () => {
|
|
const content = `## acceptance criteria
|
|
- [x] Test item
|
|
- [ ] Another test`;
|
|
|
|
const result = extractAndFormatAcceptanceCriteria(content);
|
|
expect(result).toEqual([" [x] Test item", " [ ] Another test"]);
|
|
});
|
|
});
|
|
|
|
describe("alignment consistency", () => {
|
|
test("all formatted items should start at the same column", () => {
|
|
const items: ChecklistItem[] = [
|
|
{ text: "Short", checked: true },
|
|
{ text: "Much longer item text here", checked: false },
|
|
{ text: "Medium length item", checked: true },
|
|
];
|
|
|
|
const formatted = formatChecklist(items);
|
|
|
|
// All items should start with the same padding
|
|
for (const line of formatted) {
|
|
expect(line.startsWith(" ")).toBe(true);
|
|
expect(line.charAt(0)).toBe(" ");
|
|
}
|
|
|
|
// All checkbox positions should be the same
|
|
const checkboxPositions = formatted.map((line) => line.indexOf("["));
|
|
const firstPosition = checkboxPositions[0] ?? -1;
|
|
for (const position of checkboxPositions) {
|
|
expect(position).toBe(firstPosition);
|
|
}
|
|
});
|
|
});
|
|
});
|