|
2 | 2 |
|
3 | 3 | import { render } from "lit"; |
4 | 4 | import { describe, expect, it, vi } from "vitest"; |
| 5 | +import { i18n } from "../../i18n/index.ts"; |
5 | 6 | import { getSafeLocalStorage } from "../../local-storage.ts"; |
6 | 7 | import { renderChatSessionSelect } from "../app-render.helpers.ts"; |
7 | 8 | import type { AppViewState } from "../app-view-state.ts"; |
8 | 9 | import type { GatewayBrowserClient } from "../gateway.ts"; |
9 | 10 | import type { ModelCatalogEntry } from "../types.ts"; |
10 | 11 | import type { SessionsListResult } from "../types.ts"; |
11 | 12 | import { renderChat, type ChatProps } from "./chat.ts"; |
| 13 | +import { renderOverview, type OverviewProps } from "./overview.ts"; |
12 | 14 |
|
13 | 15 | function createSessions(): SessionsListResult { |
14 | 16 | return { |
@@ -195,6 +197,57 @@ function createProps(overrides: Partial<ChatProps> = {}): ChatProps { |
195 | 197 | }; |
196 | 198 | } |
197 | 199 |
|
| 200 | +function createOverviewProps(overrides: Partial<OverviewProps> = {}): OverviewProps { |
| 201 | + return { |
| 202 | + connected: false, |
| 203 | + hello: null, |
| 204 | + settings: { |
| 205 | + gatewayUrl: "", |
| 206 | + token: "", |
| 207 | + sessionKey: "main", |
| 208 | + lastActiveSessionKey: "main", |
| 209 | + theme: "claw", |
| 210 | + themeMode: "system", |
| 211 | + chatFocusMode: false, |
| 212 | + chatShowThinking: true, |
| 213 | + chatShowToolCalls: true, |
| 214 | + splitRatio: 0.6, |
| 215 | + navCollapsed: false, |
| 216 | + navWidth: 220, |
| 217 | + navGroupsCollapsed: {}, |
| 218 | + locale: "en", |
| 219 | + }, |
| 220 | + password: "", |
| 221 | + lastError: null, |
| 222 | + lastErrorCode: null, |
| 223 | + presenceCount: 0, |
| 224 | + sessionsCount: null, |
| 225 | + cronEnabled: null, |
| 226 | + cronNext: null, |
| 227 | + lastChannelsRefresh: null, |
| 228 | + usageResult: null, |
| 229 | + sessionsResult: null, |
| 230 | + skillsReport: null, |
| 231 | + cronJobs: [], |
| 232 | + cronStatus: null, |
| 233 | + attentionItems: [], |
| 234 | + eventLog: [], |
| 235 | + overviewLogLines: [], |
| 236 | + showGatewayToken: false, |
| 237 | + showGatewayPassword: false, |
| 238 | + onSettingsChange: () => undefined, |
| 239 | + onPasswordChange: () => undefined, |
| 240 | + onSessionKeyChange: () => undefined, |
| 241 | + onToggleGatewayTokenVisibility: () => undefined, |
| 242 | + onToggleGatewayPasswordVisibility: () => undefined, |
| 243 | + onConnect: () => undefined, |
| 244 | + onRefresh: () => undefined, |
| 245 | + onNavigate: () => undefined, |
| 246 | + onRefreshLogs: () => undefined, |
| 247 | + ...overrides, |
| 248 | + }; |
| 249 | +} |
| 250 | + |
198 | 251 | describe("chat view", () => { |
199 | 252 | it("uses the assistant avatar URL for the welcome state when the identity avatar is only initials", () => { |
200 | 253 | const container = document.createElement("div"); |
@@ -285,6 +338,41 @@ describe("chat view", () => { |
285 | 338 | expect(groupedLogo?.getAttribute("src")).toBe("/openclaw/favicon.svg"); |
286 | 339 | }); |
287 | 340 |
|
| 341 | + it("keeps the persisted overview locale selected before i18n hydration finishes", async () => { |
| 342 | + const container = document.createElement("div"); |
| 343 | + const props = createOverviewProps({ |
| 344 | + settings: { |
| 345 | + ...createOverviewProps().settings, |
| 346 | + locale: "zh-CN", |
| 347 | + }, |
| 348 | + }); |
| 349 | + |
| 350 | + try { |
| 351 | + localStorage.clear(); |
| 352 | + } catch { |
| 353 | + /* noop */ |
| 354 | + } |
| 355 | + await i18n.setLocale("en"); |
| 356 | + |
| 357 | + render(renderOverview(props), container); |
| 358 | + await Promise.resolve(); |
| 359 | + |
| 360 | + let select = container.querySelector<HTMLSelectElement>("select"); |
| 361 | + expect(i18n.getLocale()).toBe("en"); |
| 362 | + expect(select?.value).toBe("zh-CN"); |
| 363 | + expect(select?.selectedOptions[0]?.textContent?.trim()).toBe("简体中文 (Simplified Chinese)"); |
| 364 | + |
| 365 | + await i18n.setLocale("zh-CN"); |
| 366 | + render(renderOverview(props), container); |
| 367 | + await Promise.resolve(); |
| 368 | + |
| 369 | + select = container.querySelector<HTMLSelectElement>("select"); |
| 370 | + expect(select?.value).toBe("zh-CN"); |
| 371 | + expect(select?.selectedOptions[0]?.textContent?.trim()).toBe("简体中文 (简体中文)"); |
| 372 | + |
| 373 | + await i18n.setLocale("en"); |
| 374 | + }); |
| 375 | + |
288 | 376 | it("renders compacting indicator as a badge", () => { |
289 | 377 | const container = document.createElement("div"); |
290 | 378 | render( |
|
0 commit comments