blob: 4a0c397406017b5e54c6c6792d2eafe87de0109c [file] [log] [blame]
Sean McCulloughb29f8912025-04-20 15:39:11 -07001import { test, expect } from "@sand4rt/experimental-ct-web";
2import { SketchContainerStatus } from "./sketch-container-status";
Sean McCullough86b56862025-04-18 13:04:03 -07003import { State } from "../types";
4
Sean McCulloughb29f8912025-04-20 15:39:11 -07005// Mock complete state for testing
6const mockCompleteState: State = {
7 hostname: "test-host",
8 working_dir: "/test/dir",
9 initial_commit: "abcdef1234567890",
10 message_count: 42,
11 os: "linux",
12 title: "Test Session",
13 total_usage: {
14 input_tokens: 1000,
15 output_tokens: 2000,
16 cache_read_input_tokens: 300,
17 cache_creation_input_tokens: 400,
18 total_cost_usd: 0.25,
19 },
20};
21
22test("render props", async ({ mount }) => {
23 const component = await mount(SketchContainerStatus, {
24 props: {
25 state: mockCompleteState,
26 },
27 });
28 await expect(component.locator("#hostname")).toContainText(
29 mockCompleteState.hostname,
30 );
31 // Check that all expected elements exist
32 await expect(component.locator("#workingDir")).toContainText(
33 mockCompleteState.working_dir,
34 );
35 await expect(component.locator("#initialCommit")).toContainText(
36 mockCompleteState.initial_commit.substring(0, 8),
37 );
38
39 await expect(component.locator("#messageCount")).toContainText(
40 mockCompleteState.message_count + "",
41 );
42 await expect(component.locator("#inputTokens")).toContainText(
43 mockCompleteState.total_usage.input_tokens + "",
44 );
45 await expect(component.locator("#outputTokens")).toContainText(
46 mockCompleteState.total_usage.output_tokens + "",
47 );
48
49 await expect(component.locator("#cacheReadInputTokens")).toContainText(
50 mockCompleteState.total_usage.cache_read_input_tokens + "",
51 );
52 await expect(component.locator("#cacheCreationInputTokens")).toContainText(
53 mockCompleteState.total_usage.cache_creation_input_tokens + "",
54 );
55 await expect(component.locator("#totalCost")).toContainText(
56 "$" + mockCompleteState.total_usage.total_cost_usd.toFixed(2),
57 );
58});
59
60test("renders with undefined state", async ({ mount }) => {
61 const component = await mount(SketchContainerStatus, {});
62
63 // Elements should exist but be empty
64 await expect(component.locator("#hostname")).toContainText("");
65 await expect(component.locator("#workingDir")).toContainText("");
66 await expect(component.locator("#initialCommit")).toContainText("");
67 await expect(component.locator("#messageCount")).toContainText("");
68 await expect(component.locator("#inputTokens")).toContainText("");
69 await expect(component.locator("#outputTokens")).toContainText("");
70 await expect(component.locator("#totalCost")).toContainText("$0.00");
71});
72
73test("renders with partial state data", async ({ mount }) => {
74 const partialState: Partial<State> = {
75 hostname: "partial-host",
76 message_count: 10,
Sean McCullough86b56862025-04-18 13:04:03 -070077 os: "linux",
Sean McCulloughb29f8912025-04-20 15:39:11 -070078 title: "Partial Test",
Sean McCullough86b56862025-04-18 13:04:03 -070079 total_usage: {
Sean McCulloughb29f8912025-04-20 15:39:11 -070080 input_tokens: 500,
Sean McCullough71941bd2025-04-18 13:31:48 -070081 },
Sean McCullough86b56862025-04-18 13:04:03 -070082 };
83
Sean McCulloughb29f8912025-04-20 15:39:11 -070084 const component = await mount(SketchContainerStatus, {
85 props: {
86 state: partialState as State,
87 },
Sean McCullough86b56862025-04-18 13:04:03 -070088 });
89
Sean McCulloughb29f8912025-04-20 15:39:11 -070090 // Check that elements with data are properly populated
91 await expect(component.locator("#hostname")).toContainText("partial-host");
92 await expect(component.locator("#messageCount")).toContainText("10");
93 await expect(component.locator("#inputTokens")).toContainText("500");
Sean McCullough86b56862025-04-18 13:04:03 -070094
Sean McCulloughb29f8912025-04-20 15:39:11 -070095 // Check that elements without data are empty
96 await expect(component.locator("#workingDir")).toContainText("");
97 await expect(component.locator("#initialCommit")).toContainText("");
98 await expect(component.locator("#outputTokens")).toContainText("");
99 await expect(component.locator("#totalCost")).toContainText("$0.00");
100});
Sean McCullough86b56862025-04-18 13:04:03 -0700101
Sean McCulloughb29f8912025-04-20 15:39:11 -0700102test("handles cost formatting correctly", async ({ mount }) => {
103 // Test with different cost values
104 const testCases = [
105 { cost: 0, expected: "$0.00" },
106 { cost: 0.1, expected: "$0.10" },
107 { cost: 1.234, expected: "$1.23" },
108 { cost: 10.009, expected: "$10.01" },
109 ];
110
111 for (const testCase of testCases) {
112 const stateWithCost = {
113 ...mockCompleteState,
Sean McCullough86b56862025-04-18 13:04:03 -0700114 total_usage: {
Sean McCulloughb29f8912025-04-20 15:39:11 -0700115 ...mockCompleteState.total_usage,
116 total_cost_usd: testCase.cost,
Sean McCullough71941bd2025-04-18 13:31:48 -0700117 },
Sean McCullough86b56862025-04-18 13:04:03 -0700118 };
119
Sean McCulloughb29f8912025-04-20 15:39:11 -0700120 const component = await mount(SketchContainerStatus, {
121 props: {
122 state: stateWithCost,
123 },
124 });
125 await expect(component.locator("#totalCost")).toContainText(
126 testCase.expected,
127 );
128 await component.unmount();
129 }
130});
Sean McCullough86b56862025-04-18 13:04:03 -0700131
Sean McCulloughb29f8912025-04-20 15:39:11 -0700132test("truncates commit hash to 8 characters", async ({ mount }) => {
133 const stateWithLongCommit = {
134 ...mockCompleteState,
135 initial_commit: "1234567890abcdef1234567890abcdef12345678",
136 };
Sean McCullough71941bd2025-04-18 13:31:48 -0700137
Sean McCulloughb29f8912025-04-20 15:39:11 -0700138 const component = await mount(SketchContainerStatus, {
139 props: {
140 state: stateWithLongCommit,
141 },
Sean McCullough86b56862025-04-18 13:04:03 -0700142 });
143
Sean McCulloughb29f8912025-04-20 15:39:11 -0700144 await expect(component.locator("#initialCommit")).toContainText("12345678");
145});
Sean McCullough86b56862025-04-18 13:04:03 -0700146
Sean McCulloughb29f8912025-04-20 15:39:11 -0700147test("has correct link elements", async ({ mount }) => {
148 const component = await mount(SketchContainerStatus, {
149 props: {
150 state: mockCompleteState,
151 },
Sean McCullough86b56862025-04-18 13:04:03 -0700152 });
153
Sean McCulloughb29f8912025-04-20 15:39:11 -0700154 // Check for logs link
155 const logsLink = component.locator("a").filter({ hasText: "Logs" });
156 await expect(logsLink).toHaveAttribute("href", "logs");
Sean McCullough86b56862025-04-18 13:04:03 -0700157
Sean McCulloughb29f8912025-04-20 15:39:11 -0700158 // Check for download link
159 const downloadLink = component.locator("a").filter({ hasText: "Download" });
160 await expect(downloadLink).toHaveAttribute("href", "download");
Sean McCullough86b56862025-04-18 13:04:03 -0700161});