



























@@ -13,6 +13,7 @@ const loadDevicesMock = vi.hoisted(() => vi.fn(async () => undefined));
1313const loadHealthStateMock = vi.hoisted(() => vi.fn(async () => undefined));
1414const loadNodesMock = vi.hoisted(() => vi.fn(async () => undefined));
1515const subscribeSessionsMock = vi.hoisted(() => vi.fn(async () => undefined));
16+const syncUrlWithSessionKeyMock = vi.hoisted(() => vi.fn());
1617const verifyPushMock = vi.hoisted(() => vi.fn(async () => undefined));
17181819type GatewayClientMock = {
@@ -23,6 +24,16 @@ type GatewayClientMock = {
23242425const gatewayClients: GatewayClientMock[] = [];
252627+function createDeferred() {
28+let resolve: () => void = () => undefined;
29+let reject: (reason?: unknown) => void = () => undefined;
30+const promise = new Promise<undefined>((res, rej) => {
31+resolve = () => res(undefined);
32+reject = rej;
33+});
34+return { promise, reject, resolve };
35+}
36+2637vi.mock("./gateway.ts", async (importOriginal) => {
2738const actual = await importOriginal<typeof import("./gateway.ts")>();
2839@@ -87,6 +98,7 @@ vi.mock("./app-settings.ts", () => ({
8798loadCron: vi.fn(),
8899refreshActiveTab: refreshActiveTabMock,
89100setLastActiveSessionKey: vi.fn(),
101+syncUrlWithSessionKey: syncUrlWithSessionKeyMock,
90102}));
9110392104vi.mock("./controllers/agents.ts", () => ({
@@ -218,10 +230,112 @@ beforeEach(() => {
218230loadHealthStateMock.mockClear();
219231loadNodesMock.mockClear();
220232subscribeSessionsMock.mockClear();
233+syncUrlWithSessionKeyMock.mockClear();
221234verifyPushMock.mockClear();
222235});
223236224237describe("connectGateway chat load startup work", () => {
238+it("starts the active chat refresh before agents.list finishes", async () => {
239+const agentsList = createDeferred();
240+loadAgentsMock.mockReturnValueOnce(agentsList.promise);
241+const { host, client } = connectHost("chat");
242+243+client.emitHello();
244+245+await vi.waitFor(() => expect(refreshActiveTabMock).toHaveBeenCalledWith(host));
246+expect(loadAgentsMock).toHaveBeenCalledWith(host);
247+expect(refreshActiveTabMock).toHaveBeenCalledTimes(1);
248+249+agentsList.resolve();
250+await agentsList.promise;
251+await Promise.resolve();
252+expect(refreshActiveTabMock).toHaveBeenCalledTimes(1);
253+});
254+255+it("waits for agents.list when a stale agent session may need fallback", async () => {
256+const agentsList = createDeferred();
257+const { host, client } = connectHost("chat");
258+loadAgentsMock.mockImplementationOnce(async () => {
259+await agentsList.promise;
260+host.agentsList = {
261+defaultId: "new-default",
262+mainKey: "main",
263+scope: "global",
264+agents: [{ id: "new-default" }],
265+};
266+});
267+host.sessionKey = "agent:old-default:main";
268+host.agentsList = {
269+defaultId: "old-default",
270+mainKey: "main",
271+scope: "global",
272+agents: [{ id: "old-default" }],
273+};
274+275+client.emitHello({
276+type: "hello-ok",
277+protocol: 4,
278+snapshot: {
279+sessionDefaults: {
280+defaultAgentId: "new-default",
281+mainKey: "main",
282+mainSessionKey: "agent:new-default:main",
283+},
284+},
285+auth: { role: "operator", scopes: [] },
286+});
287+288+await vi.waitFor(() => expect(loadAgentsMock).toHaveBeenCalledWith(host));
289+expect(refreshActiveTabMock).not.toHaveBeenCalled();
290+291+agentsList.resolve();
292+await vi.waitFor(() => expect(refreshActiveTabMock).toHaveBeenCalledWith(host));
293+expect(host.sessionKey).toBe("agent:new-default:main");
294+expect(refreshActiveTabMock).toHaveBeenCalledTimes(1);
295+});
296+297+it("waits for agents.list before refreshing selected-global chat", async () => {
298+const agentsList = createDeferred();
299+const { host, client } = connectHost("chat");
300+loadAgentsMock.mockImplementationOnce(async () => {
301+await agentsList.promise;
302+host.agentsList = {
303+defaultId: "new-default",
304+mainKey: "main",
305+scope: "global",
306+agents: [{ id: "new-default" }],
307+};
308+});
309+host.sessionKey = "global";
310+host.agentsList = {
311+defaultId: "old-default",
312+mainKey: "main",
313+scope: "global",
314+agents: [{ id: "old-default" }],
315+};
316+317+client.emitHello({
318+type: "hello-ok",
319+protocol: 4,
320+snapshot: {
321+sessionDefaults: {
322+defaultAgentId: "new-default",
323+mainKey: "main",
324+mainSessionKey: "agent:new-default:main",
325+},
326+},
327+auth: { role: "operator", scopes: [] },
328+});
329+330+await vi.waitFor(() => expect(loadAgentsMock).toHaveBeenCalledWith(host));
331+expect(refreshActiveTabMock).not.toHaveBeenCalled();
332+333+agentsList.resolve();
334+await vi.waitFor(() => expect(refreshActiveTabMock).toHaveBeenCalledWith(host));
335+expect(host.sessionKey).toBe("global");
336+expect(refreshActiveTabMock).toHaveBeenCalledTimes(1);
337+});
338+225339it("lets the active chat refresh own avatar loading on initial chat hello", async () => {
226340const { host, client } = connectHost("chat");
227341此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。