Skip to content

Commit bbf0b21

Browse files
authored
test(remote-connection): extract shared fixtures from the connection suite (#2252)
Second pass after #2243: the connect --force family, the proxy open/install pair, and the provider-allocation, persistence-failure, and proxy-disconnect scenarios build their setup from writeReplacedProfiles, seedPreviousConnection, forceConnectFlags, recordedLeaseRelease, and recordedLeaseAllocate. Titles and assertion lines are unchanged; 50 tests before and after.
1 parent d04e213 commit bbf0b21

2 files changed

Lines changed: 254 additions & 415 deletions

File tree

src/__tests__/remote-connection.fixtures.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import fs from 'node:fs';
12
import path from 'node:path';
3+
import type { CliFlags } from '@agent-device/contracts/command';
24
import type { AgentDeviceClient } from '../agent-device-client.ts';
35
import {
46
hashRemoteConfigFile,
@@ -158,3 +160,123 @@ export function seedConnectionState(options: {
158160
writeRemoteConnectionState({ stateDir: options.stateDir, state });
159161
return state;
160162
}
163+
164+
export type LeaseAllocateRequest = Parameters<AgentDeviceClient['leases']['allocate']>[0];
165+
export type LeaseReleaseRequest = Parameters<AgentDeviceClient['leases']['release']>[0];
166+
167+
/** A `leases.release` stub that reports success and keeps the last request it received. */
168+
export function recordedLeaseRelease(): {
169+
stub: AgentDeviceClient['leases']['release'];
170+
readonly request: LeaseReleaseRequest | undefined;
171+
} {
172+
let request: LeaseReleaseRequest | undefined;
173+
return {
174+
stub: async (incoming) => {
175+
request = incoming;
176+
return { released: true };
177+
},
178+
get request() {
179+
return request;
180+
},
181+
};
182+
}
183+
184+
/**
185+
* A `leases.allocate` stub that grants `leaseId` under the request's own scope and provider
186+
* fields, and keeps the last request it received.
187+
*/
188+
export function recordedLeaseAllocate(options: {
189+
leaseId: string;
190+
backend: NonNullable<LeaseAllocateRequest['leaseBackend']>;
191+
}): {
192+
stub: AgentDeviceClient['leases']['allocate'];
193+
readonly request: LeaseAllocateRequest | undefined;
194+
} {
195+
let request: LeaseAllocateRequest | undefined;
196+
return {
197+
stub: async (incoming) => {
198+
request = incoming;
199+
return {
200+
leaseId: options.leaseId,
201+
tenantId: incoming.tenant,
202+
runId: incoming.runId,
203+
backend: incoming.leaseBackend ?? options.backend,
204+
leaseProvider: incoming.leaseProvider,
205+
clientId: incoming.clientId,
206+
deviceKey: incoming.deviceKey,
207+
};
208+
},
209+
get request() {
210+
return request;
211+
},
212+
};
213+
}
214+
215+
export type ReplacedProfiles = {
216+
oldRemoteConfigPath: string;
217+
newRemoteConfigPath: string;
218+
};
219+
220+
/**
221+
* Two profile files in one workspace: the previous connection's, describing https://old.example
222+
* with `previousToken` when given, and the one `connect --force` moves to, describing
223+
* https://new.example.
224+
*/
225+
export function writeReplacedProfiles(
226+
tempRoot: string,
227+
options: { previousToken?: string } = {},
228+
): ReplacedProfiles {
229+
const oldRemoteConfigPath = path.join(tempRoot, 'old-remote.json');
230+
const newRemoteConfigPath = path.join(tempRoot, 'new-remote.json');
231+
fs.writeFileSync(
232+
oldRemoteConfigPath,
233+
JSON.stringify({
234+
daemonBaseUrl: 'https://old.example',
235+
...(options.previousToken ? { daemonAuthToken: options.previousToken } : {}),
236+
}),
237+
);
238+
fs.writeFileSync(newRemoteConfigPath, JSON.stringify({ daemonBaseUrl: 'https://new.example' }));
239+
return { oldRemoteConfigPath, newRemoteConfigPath };
240+
}
241+
242+
/**
243+
* Persists the connection a `connect --force` replaces: session `adc-android` holding lease
244+
* `lease-old` under run `run-old` against https://old.example.
245+
*/
246+
export function seedPreviousConnection(options: {
247+
stateDir: string;
248+
remoteConfigPath: string;
249+
overrides?: Partial<StoredConnectionSeed>;
250+
}): RemoteConnectionState {
251+
return seedConnectionState({
252+
stateDir: options.stateDir,
253+
state: {
254+
session: 'adc-android',
255+
remoteConfigPath: options.remoteConfigPath,
256+
tenant: 'acme',
257+
runId: 'run-old',
258+
leaseId: 'lease-old',
259+
leaseBackend: 'android-instance',
260+
daemon: { baseUrl: 'https://old.example' },
261+
...options.overrides,
262+
},
263+
});
264+
}
265+
266+
/** `connect --force` flags that move session `adc-android` to run `run-new` at https://new.example. */
267+
export function forceConnectFlags(
268+
options: { stateDir: string; remoteConfig: string } & Partial<CliFlags>,
269+
): CliFlags {
270+
return {
271+
json: true,
272+
help: false,
273+
version: false,
274+
force: true,
275+
daemonBaseUrl: 'https://new.example',
276+
tenant: 'acme',
277+
runId: 'run-new',
278+
session: 'adc-android',
279+
platform: 'android',
280+
...options,
281+
};
282+
}

0 commit comments

Comments
 (0)