Files
callstack__agent-device/test/integration/interaction-contract/coordinate.contract.test.ts
Michał Pierzchała cb65d6ca1f refactor(tests): replace the test-utils barrel with direct module imports (#1956)
* refactor(tests): replace the test-utils barrel with direct module imports

The barrel re-exported 13 modules, so every importer evaluated all of them
(store-factory alone drags 16 daemon session-store files; property-arbitraries
drags fast-check). Importing the backing modules directly cuts the unit
suite's aggregate eager module evaluations from 153,401 to 144,344 (-5.9%),
measured with the eager-import-closure walker. Deleting the barrel makes the
tax unrepresentable instead of pinning it with a guard test.

* docs(testing): point fixture guidance at the test-utils modules, not the deleted barrel

* test: extract replay session fixture
2026-08-22 12:21:35 +02:00

115 lines
4.6 KiB
TypeScript

import assert from 'node:assert/strict';
import { test } from 'vitest';
import type { InteractionGuarantee } from '@agent-device/contracts/interaction';
import { makeSnapshotState } from '../../../src/__tests__/test-utils/snapshot-builders.ts';
import { assertRpcError, assertRpcOk } from '../provider-scenarios/assertions.ts';
import { scenarioName } from './coverage-manifest.ts';
import { COORDINATE_COVERAGE } from './coordinate.coverage.ts';
import { settledWelcomeSnapshot, viewportOnlySnapshot } from './fixtures.ts';
import { createContractDevice } from './runtime-harness.ts';
import { runnerTapEntry, runnerTapErrorEntry, withIosContractDaemon } from './daemon-harness.ts';
// ADR 0011 Layer 3, coordinate path: raw x/y tap, intentionally minimal
// semantics. Path forcing is natural: a point target never resolves nodes.
const scenario = (guarantee: InteractionGuarantee): string =>
scenarioName(COORDINATE_COVERAGE, guarantee);
test(scenario('offscreen'), async () => {
const device = createContractDevice(viewportOnlySnapshot(), {
tap: async () => ({ ok: true }),
});
const result = await device.interactions.click(
{ kind: 'point', x: 500, y: 500 },
{ session: 'default' },
);
// Coordinate semantics: the escape hatch forwards the tap but must warn —
// never a silent out-of-viewport no-op, never a refusal.
assert.equal(result.kind, 'point');
assert.match(result.warning ?? '', /outside the last-known viewport \(400x800\)/);
});
test(scenario('verifyEvidence'), async () => {
let captureCount = 0;
const device = createContractDevice(viewportOnlySnapshot(), {
captureSnapshot: async () => {
captureCount += 1;
if (captureCount === 1) return { snapshot: viewportOnlySnapshot() };
return { snapshot: makeSnapshotState([]) };
},
tap: async () => ({ ok: true }),
});
const result = await device.interactions.click(
{ kind: 'point', x: 10, y: 20 },
{ session: 'default', verify: true },
);
assert.equal(result.kind, 'point');
assert.ok(result.evidence);
assert.equal(result.evidence?.changedFromBefore, true);
});
test(scenario('settleObservation'), async () => {
let captureCount = 0;
const device = createContractDevice(viewportOnlySnapshot(), {
// Point targets normally skip captures entirely; --settle opts into the
// evidence-baseline capture (first call) and the settle loop's captures.
captureSnapshot: async () => {
captureCount += 1;
if (captureCount === 1) return { snapshot: viewportOnlySnapshot() };
return { snapshot: settledWelcomeSnapshot() };
},
tap: async () => ({ ok: true }),
});
const result = await device.interactions.press(
{ kind: 'point', x: 10, y: 20 },
{ session: 'default', settle: { quietMs: 25, timeoutMs: 2_000 } },
);
assert.equal(result.kind, 'point');
const settle = result.settle;
assert.ok(settle, 'point press --settle must return a settle observation');
assert.equal(settle.settled, true);
assert.deepEqual(settle.diff?.summary, { additions: 1, removals: 1, unchanged: 0 });
});
test(scenario('errorTaxonomy'), async () => {
await withIosContractDaemon(
[runnerTapErrorEntry(new Error('runner tap crashed'))],
async (daemon) => {
const press = await daemon.callCommand('press', ['100', '200']);
// An unclassified backend failure gets the shared fallback classification
// from normalizeError: stable code, original message, actionable hint.
const error = assertRpcError(press, 'UNKNOWN', /runner tap crashed/);
assert.ok(typeof error.hint === 'string' && error.hint.length > 0);
assert.ok(typeof error.diagnosticId === 'string');
},
);
});
test(scenario('responseConstruction'), async () => {
await withIosContractDaemon([runnerTapEntry({ x: 100, y: 200 })], async (daemon) => {
const press = await daemon.callCommand('press', ['100', '200']);
const data = assertRpcOk(press);
// Canonical point response set: the tapped coordinates, no fabricated
// identity fields (the path has no resolved node by design).
assert.equal(data.x, 100);
assert.equal(data.y, 200);
assert.equal(data.ref, undefined);
assert.equal(data.selector, undefined);
});
});
// Inapplicable cell (ADR 0012), so intentionally absent from the coverage manifest.
test('coordinate resolutionDisclosure: inapplicable — no resolution field is attached', async () => {
await withIosContractDaemon([runnerTapEntry({ x: 100, y: 200 })], async (daemon) => {
const press = await daemon.callCommand('press', ['100', '200']);
const data = assertRpcOk(press);
assert.equal(data.resolution, undefined);
});
});