A bot's Oo now cheers for a moment when its run finishes, the stage Oo follows the pointer and squishes when tapped, and chat headers show the speaking bot's own Oo instead of the generic mascot. Small avatars in lists only animate while working or waiting so long lists stay calm. Claude-Session: https://claude.ai/code/session_01EKuME5CgL1ddGGN7LGvtBj Co-authored-by: Claude <noreply@anthropic.com>
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { act } from "react";
|
|
import { createRoot, type Root } from "react-dom/client";
|
|
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
|
import { BotAvatar } from "./bot-avatar.js";
|
|
|
|
let container: HTMLDivElement;
|
|
let root: Root;
|
|
|
|
beforeEach(() => {
|
|
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
|
vi.useFakeTimers();
|
|
container = document.createElement("div");
|
|
document.body.append(container);
|
|
root = createRoot(container);
|
|
});
|
|
|
|
afterEach(() => {
|
|
act(() => root.unmount());
|
|
container.remove();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
function moment() {
|
|
return container.querySelector("svg[data-oo-moment]")?.getAttribute("data-oo-moment");
|
|
}
|
|
|
|
it("celebrates when a run finishes, then settles", () => {
|
|
act(() => root.render(<BotAvatar color="#8B5CF6" status="running" size={72} />));
|
|
expect(moment()).toBe("working");
|
|
act(() => root.render(<BotAvatar color="#8B5CF6" status="completed" size={72} />));
|
|
expect(moment()).toBe("success");
|
|
act(() => vi.advanceTimersByTime(3000));
|
|
expect(moment()).toBe("idle");
|
|
});
|
|
|
|
it("does not celebrate a failed run", () => {
|
|
act(() => root.render(<BotAvatar color="#8B5CF6" status="running" size={72} />));
|
|
act(() => root.render(<BotAvatar color="#8B5CF6" status="failed" size={72} />));
|
|
expect(moment()).toBe("concerned");
|
|
});
|