Skip to content
Source
Sign inSign up
Open History to see the last commit

ConnectionsSettings.logic.test.ts

226 lines7.5 KB

1import { type DesktopWslState, EnvironmentId } from "@t3tools/contracts";
2import { describe, expect, it, vi } from "vite-plus/test";
3import {
4 applyWslEnableSelection,
5 isServerNetworkAccessible,
6 parseManualDesktopSshTarget,
7 resolveAccessEnvironmentId,
8 resolveTailscaleServeBaseUrl,
9 selectQrEndpointOption,
10 togglePairingScopeSelection,
11} from "./ConnectionsSettings.logic";
12​
13describe("togglePairingScopeSelection", () => {
14 it.each([
15 {
16 label: "adds terminal:read when terminal:operate is selected",
17 current: ["orchestration:read"],
18 scope: "terminal:operate",
19 checked: true,
20 expected: ["orchestration:read", "terminal:operate", "terminal:read"],
21 },
22 {
23 label: "drops terminal:operate when terminal:read is cleared",
24 current: ["terminal:read", "terminal:operate", "relay:read"],
25 scope: "terminal:read",
26 checked: false,
27 expected: ["relay:read"],
28 },
29 {
30 label: "keeps terminal:read when terminal:operate is cleared",
31 current: ["terminal:read", "terminal:operate"],
32 scope: "terminal:operate",
33 checked: false,
34 expected: ["terminal:read"],
35 },
36 {
37 label: "toggles unrelated scopes on their own",
38 current: ["terminal:read"],
39 scope: "filesystem:read",
40 checked: true,
41 expected: ["terminal:read", "filesystem:read"],
42 },
43 ] as const)("$label", ({ current, scope, checked, expected }) => {
44 expect(togglePairingScopeSelection(current, scope, checked)).toEqual(expected);
45 });
46});
47​
48describe("parseManualDesktopSshTarget", () => {
49 it.each(["22.5", "1e3", "2222garbage"])("rejects explicit port %j", (port) => {
50 expect(() => parseManualDesktopSshTarget({ host: "devbox", username: "", port })).toThrow(
51 "SSH port must be between 1 and 65535.",
52 );
53 });
54});
55​
56describe("resolveTailscaleServeBaseUrl", () => {
57 it.each([
58 ["https://host.tail.ts.net:441/", 443, "https://host.tail.ts.net"],
59 ["https://host.tail.ts.net:441/", 444, "https://host.tail.ts.net:444"],
60 ] as const)("previews %s on port %i", (httpBaseUrl, port, expected) => {
61 expect(resolveTailscaleServeBaseUrl({ httpBaseUrl }, port, true)).toBe(expected);
62 });
63​
64 it("returns null without a pending endpoint", () => {
65 expect(resolveTailscaleServeBaseUrl(null, 443, true)).toBeNull();
66 });
67​
68 it.each([
69 ["https://host.tail.ts.net:441/", 0, false],
70 ["not a URL", 443, true],
71 ] as const)("preserves %s when port %i cannot be previewed", (httpBaseUrl, port, isPortValid) => {
72 expect(resolveTailscaleServeBaseUrl({ httpBaseUrl }, port, isPortValid)).toBe(httpBaseUrl);
73 });
74});
75​
76const baseWslState: DesktopWslState = {
77 enabled: false,
78 distro: null,
79 available: true,
80 wslOnly: true,
81 distros: [],
82 preflightError: null,
83};
84​
85describe("applyWslEnableSelection", () => {
86 it("clears WSL-only and updates the distro before enabling both backends", async () => {
87 const calls: Array<string> = [];
88 let persistedWslOnly = true;
89 let persistedDistro: string | null = "Ubuntu";
90 const setWslDistro = vi.fn(async (distro: string | null) => {
91 calls.push(`setWslDistro:${distro ?? "default"}`);
92 persistedDistro = distro;
93 return { ...baseWslState, distro, wslOnly: persistedWslOnly };
94 });
95 const setWslBackendEnabled = vi.fn(async (enabled: boolean) => {
96 calls.push(`setWslBackendEnabled:${enabled}`);
97 return {
98 ...baseWslState,
99 enabled,
100 distro: persistedDistro,
101 wslOnly: persistedWslOnly,
102 };
103 });
104 const setWslOnly = vi.fn(async (enabled: boolean) => {
105 calls.push(`setWslOnly:${enabled}`);
106 persistedWslOnly = enabled;
107 return { ...baseWslState, distro: persistedDistro, wslOnly: enabled };
108 });
109​
110 const state = await applyWslEnableSelection({
111 bridge: { setWslDistro, setWslBackendEnabled, setWslOnly },
112 mode: "both",
113 nextDistro: "Debian",
114 persistedDistro: "Ubuntu",
115 });
116​
117 expect(calls).toEqual(["setWslOnly:false", "setWslDistro:Debian", "setWslBackendEnabled:true"]);
118 expect(state).toMatchObject({ enabled: true, distro: "Debian", wslOnly: false });
119 });
120});
121​
122describe("selectQrEndpointOption", () => {
123 const options = [
124 {
125 id: "desktop-loopback:4780",
126 preferenceKey: "desktop-core:loopback:http",
127 qrShareable: false,
128 },
129 {
130 id: "tailscale-ip:http://100.84.12.7:4780",
131 preferenceKey: "tailscale:ip:http",
132 qrShareable: true,
133 },
134 {
135 id: "tailscale-ip:http://100.84.12.8:4780",
136 preferenceKey: "tailscale:ip:http",
137 qrShareable: true,
138 },
139 {
140 id: "desktop-lan:http://192.168.1.42:4780",
141 preferenceKey: "desktop-core:lan:http",
142 qrShareable: true,
143 },
144 ];
145​
146 it("resolves an explicit selection by unique endpoint id, not the shared preference key", () => {
147 expect(selectQrEndpointOption(options, "tailscale-ip:http://100.84.12.8:4780", null)?.id).toBe(
148 "tailscale-ip:http://100.84.12.8:4780",
149 );
150 });
151​
152 it("skips non-QR-shareable options in the fallback so the panel never opens on loopback", () => {
153 expect(selectQrEndpointOption(options, "tailscale-ip:gone", "nope")?.id).toBe(
154 "tailscale-ip:http://100.84.12.7:4780",
155 );
156 });
157});
158​
159describe("resolveAccessEnvironmentId", () => {
160 const primary = EnvironmentId.make("primary");
161 const service = EnvironmentId.make("service");
162 const laptop = EnvironmentId.make("laptop");
163 it.each([
164 {
165 label: "defaults to the primary environment",
166 primaryEnvironmentId: primary,
167 environments: [
168 { environmentId: primary, connected: true },
169 { environmentId: service, connected: true },
170 ],
171 selected: null,
172 expected: primary,
173 },
174 {
175 label: "falls back to a connected saved environment without a primary",
176 primaryEnvironmentId: null,
177 environments: [
178 { environmentId: laptop, connected: false },
179 { environmentId: service, connected: true },
180 ],
181 selected: null,
182 expected: service,
183 },
184 {
185 label: "keeps an explicit choice",
186 primaryEnvironmentId: primary,
187 environments: [
188 { environmentId: primary, connected: true },
189 { environmentId: laptop, connected: false },
190 ],
191 selected: laptop,
192 expected: laptop,
193 },
194 {
195 label: "drops a choice that is no longer listed",
196 primaryEnvironmentId: null,
197 environments: [{ environmentId: service, connected: true }],
198 selected: laptop,
199 expected: service,
200 },
201 {
202 label: "has nothing to show without environments",
203 primaryEnvironmentId: null,
204 environments: [],
205 selected: null,
206 expected: null,
207 },
208 ])("$label", ({ primaryEnvironmentId, environments, selected, expected }) => {
209 expect(resolveAccessEnvironmentId({ primaryEnvironmentId, environments, selected })).toBe(
210 expected,
211 );
212 });
213});
214​
215describe("isServerNetworkAccessible", () => {
216 const served = [{ kind: "tailnet", httpBaseUrl: "https://host.example.ts.net:8443/" }] as const;
217 it.each([
218 { authPolicy: "remote-reachable", directEndpoints: undefined, expected: true },
219 { authPolicy: "loopback-browser", directEndpoints: undefined, expected: false },
220 { authPolicy: "loopback-browser", directEndpoints: [], expected: false },
221 { authPolicy: "loopback-browser", directEndpoints: served, expected: true },
222 { authPolicy: null, directEndpoints: served, expected: false },
223 ] as const)("$authPolicy with $directEndpoints.length endpoints", (row) => {
224 expect(isServerNetworkAccessible(row)).toBe(row.expected);
225 });
226});