mirror of
https://github.com/samiyev/puaros.git
synced 2025-12-28 07:16:53 +05:00
feat(ipuaro): add CLI entry point (v0.15.0)
- Add onboarding module for pre-flight checks (Redis, Ollama, model, project) - Implement start command with TUI rendering and dependency injection - Implement init command for .ipuaro.json config file creation - Implement index command for standalone project indexing - Add CLI options: --auto-apply, --model, --help, --version - Register all 18 tools via tools-setup helper - Add 29 unit tests for CLI commands - Update CHANGELOG and ROADMAP for v0.15.0
This commit is contained in:
117
packages/ipuaro/tests/unit/cli/commands/init.test.ts
Normal file
117
packages/ipuaro/tests/unit/cli/commands/init.test.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
|
||||
import * as fs from "node:fs/promises"
|
||||
import * as path from "node:path"
|
||||
import { executeInit } from "../../../../src/cli/commands/init.js"
|
||||
|
||||
vi.mock("node:fs/promises")
|
||||
|
||||
describe("executeInit", () => {
|
||||
const testPath = "/test/project"
|
||||
const configPath = path.join(testPath, ".ipuaro.json")
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
vi.spyOn(console, "warn").mockImplementation(() => {})
|
||||
vi.spyOn(console, "error").mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it("should create .ipuaro.json file successfully", async () => {
|
||||
vi.mocked(fs.access).mockRejectedValue(new Error("ENOENT"))
|
||||
vi.mocked(fs.mkdir).mockResolvedValue(undefined)
|
||||
vi.mocked(fs.writeFile).mockResolvedValue(undefined)
|
||||
|
||||
const result = await executeInit(testPath)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
expect(result.filePath).toBe(configPath)
|
||||
expect(fs.writeFile).toHaveBeenCalledWith(
|
||||
configPath,
|
||||
expect.stringContaining('"redis"'),
|
||||
"utf-8",
|
||||
)
|
||||
})
|
||||
|
||||
it("should skip existing file without force option", async () => {
|
||||
vi.mocked(fs.access).mockResolvedValue(undefined)
|
||||
|
||||
const result = await executeInit(testPath)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
expect(result.skipped).toBe(true)
|
||||
expect(fs.writeFile).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should overwrite existing file with force option", async () => {
|
||||
vi.mocked(fs.access).mockResolvedValue(undefined)
|
||||
vi.mocked(fs.writeFile).mockResolvedValue(undefined)
|
||||
|
||||
const result = await executeInit(testPath, { force: true })
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
expect(result.skipped).toBeUndefined()
|
||||
expect(fs.writeFile).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should handle write errors", async () => {
|
||||
vi.mocked(fs.access).mockRejectedValue(new Error("ENOENT"))
|
||||
vi.mocked(fs.mkdir).mockResolvedValue(undefined)
|
||||
vi.mocked(fs.writeFile).mockRejectedValue(new Error("Permission denied"))
|
||||
|
||||
const result = await executeInit(testPath)
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
expect(result.error).toContain("Permission denied")
|
||||
})
|
||||
|
||||
it("should create parent directories if needed", async () => {
|
||||
vi.mocked(fs.access)
|
||||
.mockRejectedValueOnce(new Error("ENOENT"))
|
||||
.mockRejectedValueOnce(new Error("ENOENT"))
|
||||
vi.mocked(fs.mkdir).mockResolvedValue(undefined)
|
||||
vi.mocked(fs.writeFile).mockResolvedValue(undefined)
|
||||
|
||||
const result = await executeInit(testPath)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
expect(fs.mkdir).toHaveBeenCalledWith(expect.any(String), { recursive: true })
|
||||
})
|
||||
|
||||
it("should use current directory as default", async () => {
|
||||
vi.mocked(fs.access).mockRejectedValue(new Error("ENOENT"))
|
||||
vi.mocked(fs.mkdir).mockResolvedValue(undefined)
|
||||
vi.mocked(fs.writeFile).mockResolvedValue(undefined)
|
||||
|
||||
const result = await executeInit()
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
expect(result.filePath).toContain(".ipuaro.json")
|
||||
})
|
||||
|
||||
it("should include expected config sections", async () => {
|
||||
vi.mocked(fs.access).mockRejectedValue(new Error("ENOENT"))
|
||||
vi.mocked(fs.mkdir).mockResolvedValue(undefined)
|
||||
vi.mocked(fs.writeFile).mockResolvedValue(undefined)
|
||||
|
||||
await executeInit(testPath)
|
||||
|
||||
const writeCall = vi.mocked(fs.writeFile).mock.calls[0]
|
||||
const content = writeCall[1] as string
|
||||
const config = JSON.parse(content) as {
|
||||
redis: unknown
|
||||
llm: unknown
|
||||
edit: unknown
|
||||
}
|
||||
|
||||
expect(config).toHaveProperty("redis")
|
||||
expect(config).toHaveProperty("llm")
|
||||
expect(config).toHaveProperty("edit")
|
||||
expect(config.redis).toHaveProperty("host", "localhost")
|
||||
expect(config.redis).toHaveProperty("port", 6379)
|
||||
expect(config.llm).toHaveProperty("model", "qwen2.5-coder:7b-instruct")
|
||||
expect(config.edit).toHaveProperty("autoApply", false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user