|
1 | 1 | import { test } from 'vitest'; |
2 | 2 | import assert from 'node:assert/strict'; |
| 3 | +import fs from 'node:fs'; |
| 4 | +import os from 'node:os'; |
| 5 | +import path from 'node:path'; |
3 | 6 | import { createAgentDeviceClient, type AgentDeviceClientConfig } from '../client.ts'; |
4 | 7 | import type { DaemonRequest, DaemonResponse } from '../daemon/types.ts'; |
5 | 8 | import { AppError } from '../utils/errors.ts'; |
@@ -371,6 +374,86 @@ test('client throws AppError for daemon failures', async () => { |
371 | 374 | ); |
372 | 375 | }); |
373 | 376 |
|
| 377 | +test('client.command.wait prepares selector options and rejects invalid selectors', async () => { |
| 378 | + const setup = createTransport(async () => ({ |
| 379 | + ok: true, |
| 380 | + data: {}, |
| 381 | + })); |
| 382 | + const client = createAgentDeviceClient(setup.config, { transport: setup.transport }); |
| 383 | + |
| 384 | + await client.command.wait({ |
| 385 | + selector: 'role=button[name="Continue"]', |
| 386 | + timeoutMs: 1_500, |
| 387 | + depth: 3, |
| 388 | + raw: true, |
| 389 | + }); |
| 390 | + |
| 391 | + assert.equal(setup.calls.length, 1); |
| 392 | + assert.equal(setup.calls[0]?.command, 'wait'); |
| 393 | + assert.deepEqual(setup.calls[0]?.positionals, ['role=button[name="Continue"]', '1500']); |
| 394 | + assert.equal(setup.calls[0]?.flags?.snapshotDepth, 3); |
| 395 | + assert.equal(setup.calls[0]?.flags?.snapshotRaw, true); |
| 396 | + |
| 397 | + await assert.rejects( |
| 398 | + async () => await client.command.wait({ selector: 'Continue' }), |
| 399 | + /Invalid wait selector: Continue/, |
| 400 | + ); |
| 401 | + assert.equal(setup.calls.length, 1); |
| 402 | +}); |
| 403 | + |
| 404 | +test('remote-config defaults apply across daemon-backed client methods', async () => { |
| 405 | + const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-device-client-remote-scope-')); |
| 406 | + try { |
| 407 | + const remoteConfig = path.join(tempRoot, 'remote.json'); |
| 408 | + fs.writeFileSync( |
| 409 | + remoteConfig, |
| 410 | + JSON.stringify({ |
| 411 | + session: 'remote-session', |
| 412 | + platform: 'android', |
| 413 | + daemonBaseUrl: 'http://127.0.0.1:9124/agent-device', |
| 414 | + tenant: 'remote-tenant', |
| 415 | + sessionIsolation: 'tenant', |
| 416 | + runId: 'remote-run', |
| 417 | + leaseId: 'remote-lease', |
| 418 | + }), |
| 419 | + ); |
| 420 | + const setup = createTransport(async () => ({ |
| 421 | + ok: true, |
| 422 | + data: {}, |
| 423 | + })); |
| 424 | + const client = createAgentDeviceClient( |
| 425 | + { |
| 426 | + remoteConfig, |
| 427 | + cwd: tempRoot, |
| 428 | + }, |
| 429 | + { transport: setup.transport }, |
| 430 | + ); |
| 431 | + |
| 432 | + await client.devices.list(); |
| 433 | + await client.command.home(); |
| 434 | + const snapshot = await client.capture.snapshot(); |
| 435 | + |
| 436 | + assert.equal(setup.calls[0]?.session, 'remote-session'); |
| 437 | + assert.equal(setup.calls[0]?.command, 'devices'); |
| 438 | + assert.equal(setup.calls[0]?.flags?.platform, 'android'); |
| 439 | + assert.equal(setup.calls[0]?.flags?.daemonBaseUrl, 'http://127.0.0.1:9124/agent-device'); |
| 440 | + assert.equal(setup.calls[0]?.meta?.tenantId, 'remote-tenant'); |
| 441 | + assert.equal(setup.calls[1]?.session, 'remote-session'); |
| 442 | + assert.equal(setup.calls[1]?.command, 'home'); |
| 443 | + assert.equal(setup.calls[1]?.flags?.platform, 'android'); |
| 444 | + assert.equal(setup.calls[1]?.flags?.daemonBaseUrl, 'http://127.0.0.1:9124/agent-device'); |
| 445 | + assert.equal(setup.calls[1]?.meta?.tenantId, 'remote-tenant'); |
| 446 | + assert.equal(setup.calls[1]?.meta?.runId, 'remote-run'); |
| 447 | + assert.equal(setup.calls[1]?.meta?.leaseId, 'remote-lease'); |
| 448 | + assert.equal(setup.calls[2]?.session, 'remote-session'); |
| 449 | + assert.equal(setup.calls[2]?.command, 'snapshot'); |
| 450 | + assert.equal(setup.calls[2]?.flags?.platform, 'android'); |
| 451 | + assert.equal(snapshot.identifiers.session, 'remote-session'); |
| 452 | + } finally { |
| 453 | + fs.rmSync(tempRoot, { recursive: true, force: true }); |
| 454 | + } |
| 455 | +}); |
| 456 | + |
374 | 457 | test('client capture.snapshot preserves visibility metadata from daemon responses', async () => { |
375 | 458 | const setup = createTransport(async () => ({ |
376 | 459 | ok: true, |
|
0 commit comments