mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 20:23:36 +00:00
test: enhance app specification and automaker paths tests
- Added comprehensive tests for the `specToXml` function, covering various scenarios including minimal specs, XML escaping, and optional sections. - Updated tests for `getStructuredSpecPromptInstruction` and `getAppSpecFormatInstruction` to ensure they return valid instructions. - Refactored automaker paths tests to use `path.join` for cross-platform compatibility, ensuring correct directory paths are generated.
This commit is contained in:
@@ -1,57 +1,189 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
APP_SPEC_XML_FORMAT,
|
||||
specToXml,
|
||||
getStructuredSpecPromptInstruction,
|
||||
getAppSpecFormatInstruction,
|
||||
APP_SPEC_XML_FORMAT,
|
||||
type SpecOutput,
|
||||
} from "@/lib/app-spec-format.js";
|
||||
|
||||
describe("app-spec-format.ts", () => {
|
||||
describe("APP_SPEC_XML_FORMAT", () => {
|
||||
it("should export a non-empty string constant", () => {
|
||||
expect(typeof APP_SPEC_XML_FORMAT).toBe("string");
|
||||
expect(APP_SPEC_XML_FORMAT.length).toBeGreaterThan(0);
|
||||
describe("specToXml", () => {
|
||||
it("should convert minimal spec to XML", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test Project",
|
||||
overview: "A test project",
|
||||
technology_stack: ["TypeScript", "Node.js"],
|
||||
core_capabilities: ["Testing", "Development"],
|
||||
implemented_features: [
|
||||
{ name: "Feature 1", description: "First feature" },
|
||||
],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).toContain('<?xml version="1.0" encoding="UTF-8"?>');
|
||||
expect(xml).toContain("<project_specification>");
|
||||
expect(xml).toContain("</project_specification>");
|
||||
expect(xml).toContain("<project_name>Test Project</project_name>");
|
||||
expect(xml).toContain("<technology>TypeScript</technology>");
|
||||
expect(xml).toContain("<capability>Testing</capability>");
|
||||
});
|
||||
|
||||
it("should contain XML format documentation", () => {
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<project_specification>");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("</project_specification>");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<project_name>");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<overview>");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<technology_stack>");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<core_capabilities>");
|
||||
it("should escape XML special characters", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test & Project",
|
||||
overview: "Description with <tags>",
|
||||
technology_stack: ["TypeScript"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).toContain("Test & Project");
|
||||
expect(xml).toContain("<tags>");
|
||||
});
|
||||
|
||||
it("should contain XML escaping instructions", () => {
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain(">");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("&");
|
||||
it("should include file_locations when provided", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test",
|
||||
overview: "Test",
|
||||
technology_stack: ["TS"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [
|
||||
{
|
||||
name: "Feature",
|
||||
description: "Desc",
|
||||
file_locations: ["src/index.ts"],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).toContain("<file_locations>");
|
||||
expect(xml).toContain("<location>src/index.ts</location>");
|
||||
});
|
||||
|
||||
it("should not include file_locations when empty", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test",
|
||||
overview: "Test",
|
||||
technology_stack: ["TS"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [
|
||||
{ name: "Feature", description: "Desc", file_locations: [] },
|
||||
],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).not.toContain("<file_locations>");
|
||||
});
|
||||
|
||||
it("should include additional_requirements when provided", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test",
|
||||
overview: "Test",
|
||||
technology_stack: ["TS"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [],
|
||||
additional_requirements: ["Node.js 18+"],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).toContain("<additional_requirements>");
|
||||
expect(xml).toContain("<requirement>Node.js 18+</requirement>");
|
||||
});
|
||||
|
||||
it("should include development_guidelines when provided", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test",
|
||||
overview: "Test",
|
||||
technology_stack: ["TS"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [],
|
||||
development_guidelines: ["Use ESLint"],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).toContain("<development_guidelines>");
|
||||
expect(xml).toContain("<guideline>Use ESLint</guideline>");
|
||||
});
|
||||
|
||||
it("should include implementation_roadmap when provided", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test",
|
||||
overview: "Test",
|
||||
technology_stack: ["TS"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [],
|
||||
implementation_roadmap: [
|
||||
{ phase: "Phase 1", status: "completed", description: "Setup" },
|
||||
],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).toContain("<implementation_roadmap>");
|
||||
expect(xml).toContain("<status>completed</status>");
|
||||
});
|
||||
|
||||
it("should not include optional sections when empty", () => {
|
||||
const spec: SpecOutput = {
|
||||
project_name: "Test",
|
||||
overview: "Test",
|
||||
technology_stack: ["TS"],
|
||||
core_capabilities: ["Cap"],
|
||||
implemented_features: [],
|
||||
additional_requirements: [],
|
||||
development_guidelines: [],
|
||||
implementation_roadmap: [],
|
||||
};
|
||||
|
||||
const xml = specToXml(spec);
|
||||
|
||||
expect(xml).not.toContain("<additional_requirements>");
|
||||
expect(xml).not.toContain("<development_guidelines>");
|
||||
expect(xml).not.toContain("<implementation_roadmap>");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getStructuredSpecPromptInstruction", () => {
|
||||
it("should return non-empty prompt instruction", () => {
|
||||
const instruction = getStructuredSpecPromptInstruction();
|
||||
expect(instruction).toBeTruthy();
|
||||
expect(instruction.length).toBeGreaterThan(100);
|
||||
});
|
||||
|
||||
it("should mention required fields", () => {
|
||||
const instruction = getStructuredSpecPromptInstruction();
|
||||
expect(instruction).toContain("project_name");
|
||||
expect(instruction).toContain("overview");
|
||||
expect(instruction).toContain("technology_stack");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAppSpecFormatInstruction", () => {
|
||||
it("should return a string containing the XML format", () => {
|
||||
it("should return non-empty format instruction", () => {
|
||||
const instruction = getAppSpecFormatInstruction();
|
||||
expect(typeof instruction).toBe("string");
|
||||
expect(instruction).toContain(APP_SPEC_XML_FORMAT);
|
||||
expect(instruction).toBeTruthy();
|
||||
expect(instruction.length).toBeGreaterThan(100);
|
||||
});
|
||||
|
||||
it("should contain critical formatting requirements", () => {
|
||||
it("should include critical formatting requirements", () => {
|
||||
const instruction = getAppSpecFormatInstruction();
|
||||
expect(instruction).toContain("CRITICAL FORMATTING REQUIREMENTS");
|
||||
expect(instruction).toContain("<project_specification>");
|
||||
expect(instruction).toContain("</project_specification>");
|
||||
});
|
||||
});
|
||||
|
||||
it("should contain verification instructions", () => {
|
||||
const instruction = getAppSpecFormatInstruction();
|
||||
expect(instruction).toContain("VERIFICATION");
|
||||
expect(instruction).toContain("exactly one root XML element");
|
||||
});
|
||||
|
||||
it("should instruct not to use markdown", () => {
|
||||
const instruction = getAppSpecFormatInstruction();
|
||||
expect(instruction).toContain("Do NOT use markdown");
|
||||
expect(instruction).toContain("no # headers");
|
||||
expect(instruction).toContain("no **bold**");
|
||||
describe("APP_SPEC_XML_FORMAT", () => {
|
||||
it("should contain valid XML template structure", () => {
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("<project_specification>");
|
||||
expect(APP_SPEC_XML_FORMAT).toContain("</project_specification>");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,16 +16,19 @@ import {
|
||||
} from "@/lib/automaker-paths.js";
|
||||
|
||||
describe("automaker-paths.ts", () => {
|
||||
const projectPath = "/test/project";
|
||||
const projectPath = path.join("/test", "project");
|
||||
|
||||
describe("getAutomakerDir", () => {
|
||||
it("should return path to .automaker directory", () => {
|
||||
expect(getAutomakerDir(projectPath)).toBe("/test/project/.automaker");
|
||||
expect(getAutomakerDir(projectPath)).toBe(
|
||||
path.join(projectPath, ".automaker")
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle paths with trailing slashes", () => {
|
||||
expect(getAutomakerDir("/test/project/")).toBe(
|
||||
path.join("/test/project/", ".automaker")
|
||||
const pathWithSlash = path.join("/test", "project") + path.sep;
|
||||
expect(getAutomakerDir(pathWithSlash)).toBe(
|
||||
path.join(pathWithSlash, ".automaker")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -33,7 +36,7 @@ describe("automaker-paths.ts", () => {
|
||||
describe("getFeaturesDir", () => {
|
||||
it("should return path to features directory", () => {
|
||||
expect(getFeaturesDir(projectPath)).toBe(
|
||||
"/test/project/.automaker/features"
|
||||
path.join(projectPath, ".automaker", "features")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -41,13 +44,13 @@ describe("automaker-paths.ts", () => {
|
||||
describe("getFeatureDir", () => {
|
||||
it("should return path to specific feature directory", () => {
|
||||
expect(getFeatureDir(projectPath, "feature-123")).toBe(
|
||||
"/test/project/.automaker/features/feature-123"
|
||||
path.join(projectPath, ".automaker", "features", "feature-123")
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle feature IDs with special characters", () => {
|
||||
expect(getFeatureDir(projectPath, "my-feature_v2")).toBe(
|
||||
"/test/project/.automaker/features/my-feature_v2"
|
||||
path.join(projectPath, ".automaker", "features", "my-feature_v2")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -55,27 +58,31 @@ describe("automaker-paths.ts", () => {
|
||||
describe("getFeatureImagesDir", () => {
|
||||
it("should return path to feature images directory", () => {
|
||||
expect(getFeatureImagesDir(projectPath, "feature-123")).toBe(
|
||||
"/test/project/.automaker/features/feature-123/images"
|
||||
path.join(projectPath, ".automaker", "features", "feature-123", "images")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getBoardDir", () => {
|
||||
it("should return path to board directory", () => {
|
||||
expect(getBoardDir(projectPath)).toBe("/test/project/.automaker/board");
|
||||
expect(getBoardDir(projectPath)).toBe(
|
||||
path.join(projectPath, ".automaker", "board")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getImagesDir", () => {
|
||||
it("should return path to images directory", () => {
|
||||
expect(getImagesDir(projectPath)).toBe("/test/project/.automaker/images");
|
||||
expect(getImagesDir(projectPath)).toBe(
|
||||
path.join(projectPath, ".automaker", "images")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getWorktreesDir", () => {
|
||||
it("should return path to worktrees directory", () => {
|
||||
expect(getWorktreesDir(projectPath)).toBe(
|
||||
"/test/project/.automaker/worktrees"
|
||||
path.join(projectPath, ".automaker", "worktrees")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -83,7 +90,7 @@ describe("automaker-paths.ts", () => {
|
||||
describe("getAppSpecPath", () => {
|
||||
it("should return path to app_spec.txt file", () => {
|
||||
expect(getAppSpecPath(projectPath)).toBe(
|
||||
"/test/project/.automaker/app_spec.txt"
|
||||
path.join(projectPath, ".automaker", "app_spec.txt")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -91,7 +98,7 @@ describe("automaker-paths.ts", () => {
|
||||
describe("getBranchTrackingPath", () => {
|
||||
it("should return path to active-branches.json file", () => {
|
||||
expect(getBranchTrackingPath(projectPath)).toBe(
|
||||
"/test/project/.automaker/active-branches.json"
|
||||
path.join(projectPath, ".automaker", "active-branches.json")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user