1import { EnvironmentId } from "@t3tools/contracts";
2import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay";
3import { describe, expect, it } from "vite-plus/test";
4import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
5import { relayManagedEnvironmentIds, splitEnvironmentSections } from "./environmentSections";
6
7function connectedEnvironment(
8 input: Omit<Partial<ConnectedEnvironmentSummary>, "environmentId"> & {
9 readonly environmentId: string;
10 readonly isRelayManaged: boolean;
11 },
12): ConnectedEnvironmentSummary {
13 return {
14 environmentId: EnvironmentId.make(input.environmentId),
15 environmentLabel: input.environmentLabel ?? input.environmentId,
16 displayUrl: input.displayUrl ?? `https://${input.environmentId}.example.test/`,
17 isRelayManaged: input.isRelayManaged,
18 isEnabled: input.isEnabled ?? true,
19 connectionState: input.connectionState ?? "connected",
20 connectionError: input.connectionError ?? null,
21 connectionErrorTraceId: input.connectionErrorTraceId ?? null,
22 };
23}
24
25function cloudEnvironment(environmentId: string): RelayClientEnvironmentRecord {
26 return {
27 environmentId: EnvironmentId.make(environmentId),
28 label: environmentId,
29 endpoint: {
30 httpBaseUrl: `https://${environmentId}.cloud.example.test/`,
31 wsBaseUrl: `wss://${environmentId}.cloud.example.test/ws`,
32 providerKind: "cloudflare_tunnel",
33 },
34 linkedAt: "2026-01-01T00:00:00.000Z",
35 };
36}
37
38describe("relayManagedEnvironmentIds", () => {
39 it("leaves out a backend that was saved directly", () => {
40 const ids = relayManagedEnvironmentIds([
41 connectedEnvironment({ environmentId: "environment-local", isRelayManaged: false }),
42 connectedEnvironment({ environmentId: "environment-cloud", isRelayManaged: true }),
43 ]);
44
45 expect([...ids]).toEqual([EnvironmentId.make("environment-cloud")]);
46 });
47});
48
49describe("mobile environment settings sections", () => {
50 it("keeps saved relay-managed connections under T3 Connect", () => {
51 const local = connectedEnvironment({
52 environmentId: "environment-local",
53 isRelayManaged: false,
54 });
55 const cloud = connectedEnvironment({
56 environmentId: "environment-cloud",
57 isRelayManaged: true,
58 });
59
60 const sections = splitEnvironmentSections({
61 connectedEnvironments: [cloud, local],
62 cloudEnvironments: [
63 cloudEnvironment("environment-cloud"),
64 cloudEnvironment("environment-new"),
65 ],
66 });
67
68 expect(sections.localEnvironments).toEqual([local]);
69 expect(sections.connectedCloudEnvironments).toEqual([cloud]);
70 expect(
71 sections.availableCloudEnvironments.map((environment) => environment.environmentId),
72 ).toEqual([EnvironmentId.make("environment-new")]);
73 });
74
75 it("keeps saved relay-managed connections visible when cloud listing is unavailable", () => {
76 const cloud = connectedEnvironment({
77 environmentId: "environment-cloud",
78 isRelayManaged: true,
79 connectionState: "reconnecting",
80 connectionError: "Environment did not respond before the connection timeout.",
81 });
82
83 const sections = splitEnvironmentSections({
84 connectedEnvironments: [cloud],
85 cloudEnvironments: null,
86 });
87
88 expect(sections.localEnvironments).toEqual([]);
89 expect(sections.connectedCloudEnvironments).toEqual([cloud]);
90 expect(sections.availableCloudEnvironments).toEqual([]);
91 });
92
93 it("keeps an available saved relay environment as a fallback when listing is unavailable", () => {
94 const cloud = connectedEnvironment({
95 environmentId: "environment-cloud",
96 isRelayManaged: true,
97 connectionState: "available",
98 });
99
100 const sections = splitEnvironmentSections({
101 connectedEnvironments: [cloud],
102 cloudEnvironments: null,
103 });
104
105 expect(sections.connectedCloudEnvironments).toEqual([cloud]);
106 expect(sections.availableCloudEnvironments).toEqual([]);
107 });
108
109 it("does not duplicate a saved relay environment in the available cloud listing", () => {
110 const cloud = connectedEnvironment({
111 environmentId: "environment-cloud",
112 isRelayManaged: true,
113 connectionState: "available",
114 });
115 const listedCloud = cloudEnvironment("environment-cloud");
116
117 const sections = splitEnvironmentSections({
118 connectedEnvironments: [cloud],
119 cloudEnvironments: [listedCloud],
120 });
121
122 expect(sections.connectedCloudEnvironments).toEqual([cloud]);
123 expect(sections.availableCloudEnvironments).toEqual([]);
124 });
125
126 it("still offers a cloud environment saved directly as a local backend", () => {
127 const local = connectedEnvironment({
128 environmentId: "environment-cloud",
129 isRelayManaged: false,
130 });
131
132 const sections = splitEnvironmentSections({
133 connectedEnvironments: [local],
134 cloudEnvironments: [cloudEnvironment("environment-cloud")],
135 });
136
137 expect(sections.localEnvironments).toEqual([local]);
138 expect(sections.connectedCloudEnvironments).toEqual([]);
139 expect(
140 sections.availableCloudEnvironments.map((environment) => environment.environmentId),
141 ).toEqual([EnvironmentId.make("environment-cloud")]);
142 });
143
144 it("keeps failed relay environments in the local connection row", () => {
145 const cloud = connectedEnvironment({
146 environmentId: "environment-cloud",
147 isRelayManaged: true,
148 connectionState: "error",
149 connectionError: "Connection failed.",
150 });
151
152 const sections = splitEnvironmentSections({
153 connectedEnvironments: [cloud],
154 cloudEnvironments: [cloudEnvironment("environment-cloud")],
155 });
156
157 expect(sections.connectedCloudEnvironments).toEqual([cloud]);
158 expect(sections.availableCloudEnvironments).toEqual([]);
159 });
160
161 it("offers T3 Connect for a machine saved only over the LAN, as an added route", () => {
162 const local = connectedEnvironment({
163 environmentId: "environment-desk",
164 isRelayManaged: false,
165 });
166
167 const sections = splitEnvironmentSections({
168 connectedEnvironments: [local],
169 cloudEnvironments: [cloudEnvironment("environment-desk")],
170 });
171
172 expect(sections.localEnvironments).toEqual([local]);
173 expect(
174 sections.availableCloudEnvironments.map((environment) => environment.environmentId),
175 ).toEqual([EnvironmentId.make("environment-desk")]);
176 });
177});