mirror of
https://github.com/samiyev/puaros.git
synced 2025-12-27 23:06:54 +05:00
feat(ipuaro): add display configuration
Add DisplayConfigSchema with theme support (dark/light), stats/tool calls visibility toggles, bell notification on completion, and progress bar control. Includes theme utilities with dynamic color schemes and 46 new tests.
This commit is contained in:
150
packages/ipuaro/tests/unit/shared/display-config.test.ts
Normal file
150
packages/ipuaro/tests/unit/shared/display-config.test.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Tests for DisplayConfigSchema.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from "vitest"
|
||||
import { DisplayConfigSchema } from "../../../src/shared/constants/config.js"
|
||||
|
||||
describe("DisplayConfigSchema", () => {
|
||||
describe("default values", () => {
|
||||
it("should use defaults when empty object provided", () => {
|
||||
const result = DisplayConfigSchema.parse({})
|
||||
|
||||
expect(result).toEqual({
|
||||
showStats: true,
|
||||
showToolCalls: true,
|
||||
theme: "dark",
|
||||
bellOnComplete: false,
|
||||
progressBar: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("should use defaults via .default({})", () => {
|
||||
const result = DisplayConfigSchema.default({}).parse({})
|
||||
|
||||
expect(result).toEqual({
|
||||
showStats: true,
|
||||
showToolCalls: true,
|
||||
theme: "dark",
|
||||
bellOnComplete: false,
|
||||
progressBar: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("showStats", () => {
|
||||
it("should accept true", () => {
|
||||
const result = DisplayConfigSchema.parse({ showStats: true })
|
||||
expect(result.showStats).toBe(true)
|
||||
})
|
||||
|
||||
it("should accept false", () => {
|
||||
const result = DisplayConfigSchema.parse({ showStats: false })
|
||||
expect(result.showStats).toBe(false)
|
||||
})
|
||||
|
||||
it("should reject non-boolean", () => {
|
||||
expect(() => DisplayConfigSchema.parse({ showStats: "yes" })).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe("showToolCalls", () => {
|
||||
it("should accept true", () => {
|
||||
const result = DisplayConfigSchema.parse({ showToolCalls: true })
|
||||
expect(result.showToolCalls).toBe(true)
|
||||
})
|
||||
|
||||
it("should accept false", () => {
|
||||
const result = DisplayConfigSchema.parse({ showToolCalls: false })
|
||||
expect(result.showToolCalls).toBe(false)
|
||||
})
|
||||
|
||||
it("should reject non-boolean", () => {
|
||||
expect(() => DisplayConfigSchema.parse({ showToolCalls: "yes" })).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe("theme", () => {
|
||||
it("should accept dark", () => {
|
||||
const result = DisplayConfigSchema.parse({ theme: "dark" })
|
||||
expect(result.theme).toBe("dark")
|
||||
})
|
||||
|
||||
it("should accept light", () => {
|
||||
const result = DisplayConfigSchema.parse({ theme: "light" })
|
||||
expect(result.theme).toBe("light")
|
||||
})
|
||||
|
||||
it("should reject invalid theme", () => {
|
||||
expect(() => DisplayConfigSchema.parse({ theme: "blue" })).toThrow()
|
||||
})
|
||||
|
||||
it("should reject non-string", () => {
|
||||
expect(() => DisplayConfigSchema.parse({ theme: 123 })).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe("bellOnComplete", () => {
|
||||
it("should accept true", () => {
|
||||
const result = DisplayConfigSchema.parse({ bellOnComplete: true })
|
||||
expect(result.bellOnComplete).toBe(true)
|
||||
})
|
||||
|
||||
it("should accept false", () => {
|
||||
const result = DisplayConfigSchema.parse({ bellOnComplete: false })
|
||||
expect(result.bellOnComplete).toBe(false)
|
||||
})
|
||||
|
||||
it("should reject non-boolean", () => {
|
||||
expect(() => DisplayConfigSchema.parse({ bellOnComplete: "yes" })).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe("progressBar", () => {
|
||||
it("should accept true", () => {
|
||||
const result = DisplayConfigSchema.parse({ progressBar: true })
|
||||
expect(result.progressBar).toBe(true)
|
||||
})
|
||||
|
||||
it("should accept false", () => {
|
||||
const result = DisplayConfigSchema.parse({ progressBar: false })
|
||||
expect(result.progressBar).toBe(false)
|
||||
})
|
||||
|
||||
it("should reject non-boolean", () => {
|
||||
expect(() => DisplayConfigSchema.parse({ progressBar: "yes" })).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe("partial config", () => {
|
||||
it("should merge partial config with defaults", () => {
|
||||
const result = DisplayConfigSchema.parse({
|
||||
theme: "light",
|
||||
bellOnComplete: true,
|
||||
})
|
||||
|
||||
expect(result).toEqual({
|
||||
showStats: true,
|
||||
showToolCalls: true,
|
||||
theme: "light",
|
||||
bellOnComplete: true,
|
||||
progressBar: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("full config", () => {
|
||||
it("should accept valid full config", () => {
|
||||
const config = {
|
||||
showStats: false,
|
||||
showToolCalls: false,
|
||||
theme: "light" as const,
|
||||
bellOnComplete: true,
|
||||
progressBar: false,
|
||||
}
|
||||
|
||||
const result = DisplayConfigSchema.parse(config)
|
||||
expect(result).toEqual(config)
|
||||
})
|
||||
})
|
||||
})
|
||||
29
packages/ipuaro/tests/unit/tui/utils/bell.test.ts
Normal file
29
packages/ipuaro/tests/unit/tui/utils/bell.test.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Tests for bell utility.
|
||||
*/
|
||||
|
||||
import { describe, expect, it, vi } from "vitest"
|
||||
import { ringBell } from "../../../../src/tui/utils/bell.js"
|
||||
|
||||
describe("ringBell", () => {
|
||||
it("should write bell character to stdout", () => {
|
||||
const writeSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true)
|
||||
|
||||
ringBell()
|
||||
|
||||
expect(writeSpy).toHaveBeenCalledWith("\u0007")
|
||||
writeSpy.mockRestore()
|
||||
})
|
||||
|
||||
it("should write correct ASCII bell character", () => {
|
||||
const writeSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true)
|
||||
|
||||
ringBell()
|
||||
|
||||
const callArg = writeSpy.mock.calls[0]?.[0]
|
||||
expect(callArg).toBe("\u0007")
|
||||
expect(callArg?.charCodeAt(0)).toBe(7)
|
||||
|
||||
writeSpy.mockRestore()
|
||||
})
|
||||
})
|
||||
158
packages/ipuaro/tests/unit/tui/utils/theme.test.ts
Normal file
158
packages/ipuaro/tests/unit/tui/utils/theme.test.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Tests for theme utilities.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from "vitest"
|
||||
import { getColorScheme, getContextColor, getRoleColor, getStatusColor } from "../../../../src/tui/utils/theme.js"
|
||||
|
||||
describe("theme utilities", () => {
|
||||
describe("getColorScheme", () => {
|
||||
it("should return dark theme colors for dark", () => {
|
||||
const scheme = getColorScheme("dark")
|
||||
|
||||
expect(scheme).toEqual({
|
||||
primary: "cyan",
|
||||
secondary: "blue",
|
||||
success: "green",
|
||||
warning: "yellow",
|
||||
error: "red",
|
||||
info: "cyan",
|
||||
muted: "gray",
|
||||
background: "black",
|
||||
foreground: "white",
|
||||
})
|
||||
})
|
||||
|
||||
it("should return light theme colors for light", () => {
|
||||
const scheme = getColorScheme("light")
|
||||
|
||||
expect(scheme).toEqual({
|
||||
primary: "blue",
|
||||
secondary: "cyan",
|
||||
success: "green",
|
||||
warning: "yellow",
|
||||
error: "red",
|
||||
info: "blue",
|
||||
muted: "gray",
|
||||
background: "white",
|
||||
foreground: "black",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("getStatusColor", () => {
|
||||
it("should return success color for ready status", () => {
|
||||
const color = getStatusColor("ready", "dark")
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
|
||||
it("should return warning color for thinking status", () => {
|
||||
const color = getStatusColor("thinking", "dark")
|
||||
expect(color).toBe("yellow")
|
||||
})
|
||||
|
||||
it("should return warning color for tool_call status", () => {
|
||||
const color = getStatusColor("tool_call", "dark")
|
||||
expect(color).toBe("yellow")
|
||||
})
|
||||
|
||||
it("should return info color for awaiting_confirmation status", () => {
|
||||
const color = getStatusColor("awaiting_confirmation", "dark")
|
||||
expect(color).toBe("cyan")
|
||||
})
|
||||
|
||||
it("should return error color for error status", () => {
|
||||
const color = getStatusColor("error", "dark")
|
||||
expect(color).toBe("red")
|
||||
})
|
||||
|
||||
it("should use light theme colors when theme is light", () => {
|
||||
const color = getStatusColor("awaiting_confirmation", "light")
|
||||
expect(color).toBe("blue")
|
||||
})
|
||||
|
||||
it("should use dark theme by default", () => {
|
||||
const color = getStatusColor("ready")
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
})
|
||||
|
||||
describe("getRoleColor", () => {
|
||||
it("should return success color for user role", () => {
|
||||
const color = getRoleColor("user", "dark")
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
|
||||
it("should return primary color for assistant role", () => {
|
||||
const color = getRoleColor("assistant", "dark")
|
||||
expect(color).toBe("cyan")
|
||||
})
|
||||
|
||||
it("should return muted color for system role", () => {
|
||||
const color = getRoleColor("system", "dark")
|
||||
expect(color).toBe("gray")
|
||||
})
|
||||
|
||||
it("should return secondary color for tool role", () => {
|
||||
const color = getRoleColor("tool", "dark")
|
||||
expect(color).toBe("blue")
|
||||
})
|
||||
|
||||
it("should use light theme colors when theme is light", () => {
|
||||
const color = getRoleColor("assistant", "light")
|
||||
expect(color).toBe("blue")
|
||||
})
|
||||
|
||||
it("should use dark theme by default", () => {
|
||||
const color = getRoleColor("user")
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
})
|
||||
|
||||
describe("getContextColor", () => {
|
||||
it("should return success color for low usage", () => {
|
||||
const color = getContextColor(0.5, "dark")
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
|
||||
it("should return warning color for medium usage", () => {
|
||||
const color = getContextColor(0.7, "dark")
|
||||
expect(color).toBe("yellow")
|
||||
})
|
||||
|
||||
it("should return error color for high usage", () => {
|
||||
const color = getContextColor(0.9, "dark")
|
||||
expect(color).toBe("red")
|
||||
})
|
||||
|
||||
it("should return success color at 59% usage", () => {
|
||||
const color = getContextColor(0.59, "dark")
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
|
||||
it("should return warning color at 60% usage", () => {
|
||||
const color = getContextColor(0.6, "dark")
|
||||
expect(color).toBe("yellow")
|
||||
})
|
||||
|
||||
it("should return warning color at 79% usage", () => {
|
||||
const color = getContextColor(0.79, "dark")
|
||||
expect(color).toBe("yellow")
|
||||
})
|
||||
|
||||
it("should return error color at 80% usage", () => {
|
||||
const color = getContextColor(0.8, "dark")
|
||||
expect(color).toBe("red")
|
||||
})
|
||||
|
||||
it("should use light theme colors when theme is light", () => {
|
||||
const color = getContextColor(0.7, "light")
|
||||
expect(color).toBe("yellow")
|
||||
})
|
||||
|
||||
it("should use dark theme by default", () => {
|
||||
const color = getContextColor(0.5)
|
||||
expect(color).toBe("green")
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user