UI: fix mounted avatar meta fallback

This commit is contained in:
Vincent Koc
2026-03-12 23:39:27 -04:00
parent c52f23f794
commit 7509c4a057
2 changed files with 66 additions and 1 deletions

View File

@@ -0,0 +1,65 @@
/* @vitest-environment jsdom */
import { afterEach, describe, expect, it, vi } from "vitest";
import { refreshChatAvatar, type ChatHost } from "./app-chat.ts";
function makeHost(overrides?: Partial<ChatHost>): ChatHost {
return {
client: null,
chatMessages: [],
chatStream: null,
connected: true,
chatMessage: "",
chatAttachments: [],
chatQueue: [],
chatRunId: null,
chatSending: false,
lastError: null,
sessionKey: "agent:main",
basePath: "",
hello: null,
chatAvatarUrl: null,
refreshSessionsAfterChat: new Set<string>(),
...overrides,
};
}
describe("refreshChatAvatar", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
it("uses a route-relative avatar endpoint before basePath bootstrap finishes", async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ avatarUrl: "/avatar/main" }),
});
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
const host = makeHost({ basePath: "", sessionKey: "agent:main" });
await refreshChatAvatar(host);
expect(fetchMock).toHaveBeenCalledWith(
"avatar/main?meta=1",
expect.objectContaining({ method: "GET" }),
);
expect(host.chatAvatarUrl).toBe("/avatar/main");
});
it("keeps mounted dashboard avatar endpoints under the normalized base path", async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: false,
json: async () => ({}),
});
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
const host = makeHost({ basePath: "/openclaw/", sessionKey: "agent:ops:main" });
await refreshChatAvatar(host);
expect(fetchMock).toHaveBeenCalledWith(
"/openclaw/avatar/ops?meta=1",
expect.objectContaining({ method: "GET" }),
);
expect(host.chatAvatarUrl).toBeNull();
});
});

View File

@@ -372,7 +372,7 @@ function resolveAgentIdForSession(host: ChatHost): string | null {
function buildAvatarMetaUrl(basePath: string, agentId: string): string {
const base = normalizeBasePath(basePath);
const encoded = encodeURIComponent(agentId);
return base ? `${base}/avatar/${encoded}?meta=1` : `/avatar/${encoded}?meta=1`;
return base ? `${base}/avatar/${encoded}?meta=1` : `avatar/${encoded}?meta=1`;
}
export async function refreshChatAvatar(host: ChatHost) {