1import {
2 EnvironmentId,
3 ORCHESTRATION_PROTOCOL_VERSION,
4 type ExecutionEnvironmentDescriptor,
5} from "@t3tools/contracts";
6import { describe, expect, it } from "vite-plus/test";
7
8import {
9 appendOrchestrationProtocol,
10 orchestrationProtocolCompatibilityError,
11} from "./compatibility.ts";
12
13const descriptor = (orchestrationProtocolVersion?: number): ExecutionEnvironmentDescriptor => ({
14 environmentId: EnvironmentId.make("environment-remote"),
15 label: "Build Mac",
16 platform: { os: "darwin", arch: "arm64" },
17 serverVersion: "9.0.0",
18 ...(orchestrationProtocolVersion === undefined ? {} : { orchestrationProtocolVersion }),
19 capabilities: { repositoryIdentity: true },
20});
21
22describe("orchestration protocol compatibility", () => {
23 it("accepts the current protocol and announces it without disturbing socket credentials", () => {
24 expect(
25 orchestrationProtocolCompatibilityError(descriptor(ORCHESTRATION_PROTOCOL_VERSION)),
26 ).toBeNull();
27
28 const socketUrl = new URL(
29 appendOrchestrationProtocol("wss://host.test/ws?wsTicket=secret&connectionMethod=relay"),
30 );
31 expect(socketUrl.searchParams.get("orchestrationProtocol")).toBe(
32 String(ORCHESTRATION_PROTOCOL_VERSION),
33 );
34 expect(socketUrl.searchParams.get("wsTicket")).toBe("secret");
35 expect(socketUrl.searchParams.get("connectionMethod")).toBe("relay");
36 });
37
38 it("treats missing metadata as protocol 1", () => {
39 const error = orchestrationProtocolCompatibilityError(descriptor());
40 if (Number(ORCHESTRATION_PROTOCOL_VERSION) === 1) {
41 expect(error).toBeNull();
42 } else {
43 expect(error).toMatchObject({ reason: "unsupported" });
44 }
45 });
46
47 it("blocks a different protocol before connecting", () => {
48 const error = orchestrationProtocolCompatibilityError(
49 descriptor(ORCHESTRATION_PROTOCOL_VERSION + 1),
50 );
51 expect(error).toMatchObject({ reason: "unsupported" });
52 expect(error?.message).toContain("This client is not supported");
53 expect(error).not.toHaveProperty("serverUpdateRequired");
54 });
55
56 it("offers a remote update only for an older host that can update itself", () => {
57 const older = descriptor(ORCHESTRATION_PROTOCOL_VERSION - 1);
58 const withCapabilities = (capabilities: ExecutionEnvironmentDescriptor["capabilities"]) =>
59 orchestrationProtocolCompatibilityError({ ...older, capabilities });
60
61 expect(
62 withCapabilities({ repositoryIdentity: true, serverSelfUpdate: "boot-service" }),
63 ).toMatchObject({ serverUpdateRequired: true });
64 expect(withCapabilities({ repositoryIdentity: true })).not.toHaveProperty(
65 "serverUpdateRequired",
66 );
67 expect(
68 withCapabilities({ repositoryIdentity: true, serverSelfUpdate: "desktop-managed" }),
69 ).not.toHaveProperty("serverUpdateRequired");
70 expect(
71 withCapabilities({
72 repositoryIdentity: true,
73 serverSelfUpdate: "desktop-managed",
74 desktopAppUpdate: true,
75 }),
76 ).toMatchObject({ serverUpdateRequired: true });
77 });
78});