fix(session-sharing): use the linked server for desktop meetings and links (#1507)

This commit is contained in:
ZacharyZcR authored and GitHub committed 2026-09-30 09:54:23 -05:00
1 parent 9801cc7fc7
commit ec7c2c2835
15 files changed
+621 -210

No files matched your search

@@ -0,0 +1,80 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import type { PluginApiClient, TermixApp } from "@termix/plugin-sdk/frontend";
import {
connectMeetings,
meetingGuestUrl,
} from "../../src/frontend/meeting-backend";
function client(): PluginApiClient {
return Object.fromEntries(
["get", "post", "put", "patch", "delete"].map((method) => [
method,
vi.fn(async () => ({ data: { rooms: [] } })),
]),
) as unknown as PluginApiClient;
}
afterEach(() => vi.restoreAllMocks());
describe("meeting backend", () => {
it("routes rooms, invites and host resolution to the linked server and refuses a later switch", async () => {
const local = client();
const remote = client();
let url: string | null = "https://termix.example/base/";
const app = {
desktop: { available: true, remoteServerUrl: async () => url },
apiFor: (origin: string) => (origin === "remote" ? remote : local),
t: (key: string) => key,
} as unknown as TermixApp;
const backend = await connectMeetings(app);
expect(backend.origin).toBe("remote");
await backend.api.listCollabRooms();
await backend.api.createCollabRoom("Standup", true);
await backend.api.getDirectory();
await backend.api.resolveHost("stable-host-id");
await backend.api.presentCollabStage("room", {
hostId: 99,
sessionId: "remote-session",
protocol: "ssh",
});
expect(local.get).not.toHaveBeenCalled();
expect(local.post).not.toHaveBeenCalled();
expect(remote.get).toHaveBeenCalledWith("/meeting-host/stable-host-id");
expect(remote.post).toHaveBeenCalledWith("/rooms/room/present", {
hostId: 99,
sessionId: "remote-session",
protocol: "ssh",
});
expect(meetingGuestUrl(backend.publicUrl, "a+b&c")).toBe(
"https://termix.example/base/?view=collab-guest&token=a%2Bb%26c",
);
url = "https://other.example";
await expect(backend.api.deleteCollabRoom("room")).rejects.toThrow(
"collab.serverChanged",
);
expect(remote.delete).not.toHaveBeenCalled();
url = null;
await expect(backend.api.getCollabRoom("room")).rejects.toThrow(
"collab.serverChanged",
);
});
it("keeps standalone rooms local without generating a file URL", async () => {
const local = client();
const backend = await connectMeetings({
desktop: { available: true, remoteServerUrl: async () => null },
apiFor: () => local,
t: (key: string) => key,
} as unknown as TermixApp);
expect(backend.origin).toBe("local");
await backend.api.listCollabRooms();
expect(local.get).toHaveBeenCalledWith("/rooms");
expect(meetingGuestUrl(backend.publicUrl, "token")).toBeNull();
expect(meetingGuestUrl("file:///app/index.html", "token")).toBeNull();
});
it("preserves web deployment paths while replacing old query and fragment values", () => {
expect(
meetingGuestUrl("https://termix.example/app/?view=other#old", "token"),
).toBe("https://termix.example/app/?view=collab-guest&token=token");
});
});
@@ -0,0 +1,29 @@
import { describe, expect, it, vi } from "vitest";
const { pluginWsUrl } = vi.hoisted(() => ({ pluginWsUrl: vi.fn() }));
vi.mock("@termix/plugin-sdk/ui", () => ({ pluginWsUrl }));
import { wsTargetForPath } from "../../src/frontend/shared";
describe("meeting event transport", () => {
it("preserves remote authentication protocols and event query parameters", async () => {
pluginWsUrl.mockResolvedValue({
url: "wss://server/base/plugin-ws/ssh-terminal/terminal",
protocols: ["jwt", "session-token"],
});
expect(
await wsTargetForPath(
"/plugin-ws/ssh-terminal/terminal?room=abc",
"remote",
),
).toEqual({
url: "wss://server/base/plugin-ws/ssh-terminal/terminal?room=abc",
protocols: ["jwt", "session-token"],
});
expect(pluginWsUrl).toHaveBeenCalledWith("ssh-terminal", "/terminal", {
origin: "remote",
});
expect(
await wsTargetForPath("https://another-server/ws", "remote"),
).toBeNull();
});
});