generated from nhcarrigan/template
feat: multiple UI improvements, font settings, and memory file display names (#175)
## Summary - **fix**: `show_thinking_blocks` setting now persists across sessions — it was defined on the TypeScript side but missing from the Rust `HikariConfig` struct, so serde silently dropped it on every save/load - **feat**: Tool calls are now rendered as collapsible blocks matching the Extended Thinking block aesthetic, replacing the old inline dropdown approach - **feat**: Add configurable max output tokens setting - **feat**: Use random creative names for conversation tabs - **test**: Significantly expanded frontend unit test coverage - **docs**: Require tests for all changes in CLAUDE.md - **feat**: Allow users to specify a custom terminal font (Closes #176) - **feat**: Display friendly names for memory files derived from the first heading (Closes #177) - **feat**: Add custom UI font support for the app chrome (buttons, labels, tabs) - **fix**: Apply custom UI font to the full app interface — `.app-container` was hardcoded, blocking inheritance from `body`; also renamed "Custom Font" to "Custom Terminal Font" for clarity ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #175 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #175.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import { get } from "svelte/store";
|
||||
import { emitMockEvent } from "../../../vitest.setup";
|
||||
import { todos, initializeTodoListener, cleanupTodoListener } from "./todos";
|
||||
import type { TodoItem } from "./todos";
|
||||
|
||||
describe("todos store", () => {
|
||||
beforeEach(() => {
|
||||
cleanupTodoListener();
|
||||
todos.clear();
|
||||
});
|
||||
|
||||
describe("initial state", () => {
|
||||
it("starts with an empty list", () => {
|
||||
expect(get(todos)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("set and clear", () => {
|
||||
it("can set todos directly", () => {
|
||||
const items: TodoItem[] = [
|
||||
{ content: "Task 1", status: "pending", activeForm: "Doing task 1" },
|
||||
{ content: "Task 2", status: "in_progress", activeForm: "Doing task 2" },
|
||||
];
|
||||
todos.set(items);
|
||||
expect(get(todos)).toEqual(items);
|
||||
});
|
||||
|
||||
it("clear resets to empty array", () => {
|
||||
todos.set([{ content: "Task", status: "completed", activeForm: "Doing task" }]);
|
||||
todos.clear();
|
||||
expect(get(todos)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("update", () => {
|
||||
it("can update todos with a callback", () => {
|
||||
const initial: TodoItem[] = [
|
||||
{ content: "Task 1", status: "pending", activeForm: "Doing task 1" },
|
||||
];
|
||||
todos.set(initial);
|
||||
todos.update((current) => [
|
||||
...current,
|
||||
{ content: "Task 2", status: "completed", activeForm: "Doing task 2" },
|
||||
]);
|
||||
expect(get(todos)).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("initializeTodoListener", () => {
|
||||
it("listens for claude:todo-update events", async () => {
|
||||
await initializeTodoListener();
|
||||
|
||||
const newTodos: TodoItem[] = [
|
||||
{ content: "Backend task", status: "in_progress", activeForm: "Running backend task" },
|
||||
];
|
||||
emitMockEvent("claude:todo-update", { todos: newTodos });
|
||||
|
||||
expect(get(todos)).toEqual(newTodos);
|
||||
});
|
||||
|
||||
it("does not register a duplicate listener when called twice", async () => {
|
||||
await initializeTodoListener();
|
||||
await initializeTodoListener();
|
||||
|
||||
const newTodos: TodoItem[] = [
|
||||
{ content: "Task", status: "pending", activeForm: "Doing task" },
|
||||
];
|
||||
emitMockEvent("claude:todo-update", { todos: newTodos });
|
||||
|
||||
// Should only have been set once (not doubled)
|
||||
expect(get(todos)).toEqual(newTodos);
|
||||
});
|
||||
});
|
||||
|
||||
describe("cleanupTodoListener", () => {
|
||||
it("stops listening for events after cleanup", async () => {
|
||||
await initializeTodoListener();
|
||||
cleanupTodoListener();
|
||||
|
||||
emitMockEvent("claude:todo-update", {
|
||||
todos: [{ content: "Task", status: "pending", activeForm: "Doing task" }],
|
||||
});
|
||||
|
||||
// Should not have been updated since we cleaned up
|
||||
expect(get(todos)).toEqual([]);
|
||||
});
|
||||
|
||||
it("is safe to call when not initialised", () => {
|
||||
expect(() => cleanupTodoListener()).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user