diff --git a/ui/src/components/agent-select.test.ts b/ui/src/components/agent-select.test.ts index 08f032d125b7..ca4776fad7c1 100644 --- a/ui/src/components/agent-select.test.ts +++ b/ui/src/components/agent-select.test.ts @@ -3,7 +3,15 @@ import { expect, it, vi } from "vitest"; import type { AgentIdentityResult, GatewayAgentRow } from "../api/types.ts"; import { i18n, t } from "../i18n/index.ts"; -import "./agent-select.ts"; +import { AgentSelect } from "./agent-select.ts"; + +const AGENT_SELECT_TEST_TAG = "test-openclaw-agent-select"; + +// The shared jsdom registry outlives Vitest's per-file module reset. Use the +// freshly imported class so locale state and the element controller stay paired. +if (!customElements.get(AGENT_SELECT_TEST_TAG)) { + customElements.define(AGENT_SELECT_TEST_TAG, class extends AgentSelect {}); +} type AgentSelectElement = HTMLElement & { agents: GatewayAgentRow[]; @@ -36,7 +44,7 @@ function createIdentity( async function createAgentSelect( overrides: Partial> = {}, ): Promise { - const element = document.createElement("openclaw-agent-select") as AgentSelectElement; + const element = document.createElement(AGENT_SELECT_TEST_TAG) as AgentSelectElement; element.agents = agents; element.selectedId = "alpha"; Object.assign(element, overrides); @@ -336,8 +344,9 @@ it("refreshes translated labels when the locale changes while mounted", async () await i18n.setLocale("zh-CN"); await element.updateComplete; - expect(label?.textContent?.trim()).toBe(t("agents.noAgents")); - expect(label?.textContent?.trim()).not.toBe(englishLabel); + const translatedLabel = element.querySelector(".agent-select__label"); + expect(translatedLabel?.textContent?.trim()).toBe(t("agents.noAgents")); + expect(translatedLabel?.textContent?.trim()).not.toBe(englishLabel); } finally { element.remove(); await i18n.setLocale("en"); diff --git a/ui/src/components/agent-select.ts b/ui/src/components/agent-select.ts index 3a7359449655..5ca9933f5b38 100644 --- a/ui/src/components/agent-select.ts +++ b/ui/src/components/agent-select.ts @@ -11,7 +11,7 @@ import { resolveAgentAvatarUrl } from "../lib/avatar.ts"; import { OpenClawLightDomElement } from "../lit/openclaw-element.ts"; import { icons } from "./icons.ts"; -class AgentSelect extends OpenClawLightDomElement { +export class AgentSelect extends OpenClawLightDomElement { @property({ attribute: false }) agents: GatewayAgentRow[] = []; @property({ attribute: false }) selectedId: string | null = null; @property({ attribute: false }) defaultId: string | null = null; diff --git a/ui/src/pages/profile/profile-page.test.ts b/ui/src/pages/profile/profile-page.test.ts index 75b96c81698e..7deef8fb4922 100644 --- a/ui/src/pages/profile/profile-page.test.ts +++ b/ui/src/pages/profile/profile-page.test.ts @@ -10,9 +10,10 @@ import { type ApplicationGatewaySnapshot, } from "../../app/context.ts"; import { i18n, t } from "../../i18n/index.ts"; -import "./profile-page.ts"; +import { ProfilePage } from "./profile-page.ts"; const PROVIDER_ELEMENT_NAME = "test-profile-page-context-provider"; +const PROFILE_PAGE_TEST_TAG = "test-openclaw-profile-page"; class ProfilePageContextProvider extends LitElement { private readonly contextProvider = new ContextProvider(this, { @@ -27,6 +28,10 @@ class ProfilePageContextProvider extends LitElement { if (!customElements.get(PROVIDER_ELEMENT_NAME)) { customElements.define(PROVIDER_ELEMENT_NAME, ProfilePageContextProvider); } +// Keep the element class on the same post-reset i18n module as this test. +if (!customElements.get(PROFILE_PAGE_TEST_TAG)) { + customElements.define(PROFILE_PAGE_TEST_TAG, class extends ProfilePage {}); +} type ProfilePageElement = HTMLElement & { updateComplete: Promise; @@ -62,7 +67,7 @@ afterEach(async () => { it("refreshes translated copy when the locale changes while mounted", async () => { const provider = document.createElement(PROVIDER_ELEMENT_NAME) as ProfilePageContextProvider; - const page = document.createElement("openclaw-profile-page") as ProfilePageElement; + const page = document.createElement(PROFILE_PAGE_TEST_TAG) as ProfilePageElement; provider.setContext(createContext()); provider.append(page); document.body.append(provider); diff --git a/ui/src/pages/profile/profile-page.ts b/ui/src/pages/profile/profile-page.ts index bc2b37c9e784..a4f7ff77fb58 100644 --- a/ui/src/pages/profile/profile-page.ts +++ b/ui/src/pages/profile/profile-page.ts @@ -85,7 +85,7 @@ function toErrorMessage(error: unknown): string { return typeof error === "string" ? error : "request failed"; } -class ProfilePage extends OpenClawLightDomElement { +export class ProfilePage extends OpenClawLightDomElement { @consume({ context: applicationContext, subscribe: false }) private context!: ApplicationContext; @@ -540,4 +540,6 @@ class ProfilePage extends OpenClawLightDomElement { } } -customElements.define("openclaw-profile-page", ProfilePage); +if (!customElements.get("openclaw-profile-page")) { + customElements.define("openclaw-profile-page", ProfilePage); +}