Skip to content

Commit d7a7ce4

Browse files
committed
refactor: tighten Maestro replay compatibility boundary
1 parent 3d9ae49 commit d7a7ce4

18 files changed

Lines changed: 94 additions & 53 deletions

ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ extension RunnerTests {
256256
app: activeApp,
257257
selectorKey: selectorKey,
258258
selectorValue: selectorValue,
259-
allowNonHittableFallback: command.allowNonHittableSelectorTap == true
259+
allowNonHittableFallback: command.allowNonHittableCoordinateFallback == true
260260
)
261261
if match.isAmbiguous {
262262
return Response(ok: false, error: ErrorPayload(code: "AMBIGUOUS_MATCH", message: "selector matched multiple elements"))
@@ -877,7 +877,7 @@ extension RunnerTests {
877877
app: activeApp,
878878
selectorKey: selectorKey,
879879
selectorValue: selectorValue,
880-
allowNonHittableFallback: command.allowNonHittableSelectorTap == true
880+
allowNonHittableFallback: command.allowNonHittableCoordinateFallback == true
881881
)
882882
if match.isAmbiguous {
883883
return Response(ok: false, error: ErrorPayload(code: "AMBIGUOUS_MATCH", message: "selector matched multiple elements"))

ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct Command: Codable {
4040
let text: String?
4141
let selectorKey: String?
4242
let selectorValue: String?
43-
let allowNonHittableSelectorTap: Bool?
43+
let allowNonHittableCoordinateFallback: Bool?
4444
let delayMs: Int?
4545
let textEntryMode: String?
4646
let clearFirst: Bool?

src/compat/maestro/__tests__/replay-flow.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ env:
8080
assert.equal(parsed.actions[3]?.flags.doubleTap, true);
8181
assert.equal(parsed.actions[3]?.flags.intervalMs, 150);
8282
assert.equal(parsed.actions[4]?.flags.holdMs, 3000);
83-
assert.equal(parsed.actions[1]?.flags.maestro?.allowNonHittableSelectorTap, true);
84-
assert.equal(parsed.actions[6]?.flags?.maestro?.allowNonHittableSelectorTap, undefined);
83+
assert.equal(parsed.actions[1]?.flags.maestro?.allowNonHittableCoordinateFallback, true);
84+
assert.equal(parsed.actions[6]?.flags?.maestro?.allowNonHittableCoordinateFallback, undefined);
8585
});
8686

8787
test('parseMaestroReplayFlow maps iOS openLink through the app id when available', () => {
@@ -200,7 +200,7 @@ test('parseMaestroReplayFlow marks tapOn before inputText for snapshot tap focus
200200
['type', ['Muted Users']],
201201
],
202202
);
203-
assert.equal(parsed.actions[0]?.flags?.maestro?.allowNonHittableSelectorTap, undefined);
203+
assert.equal(parsed.actions[0]?.flags?.maestro?.allowNonHittableCoordinateFallback, undefined);
204204
});
205205

206206
test('parseMaestroReplayFlow coalesces tapOn inputText while preserving pressKey Enter submit', () => {
@@ -221,7 +221,7 @@ test('parseMaestroReplayFlow coalesces tapOn inputText while preserving pressKey
221221
],
222222
);
223223
assert.deepEqual(parsed.actionLines, [3, 3, 6]);
224-
assert.equal(parsed.actions[1]?.flags?.maestro?.allowNonHittableSelectorTap, true);
224+
assert.equal(parsed.actions[1]?.flags?.maestro?.allowNonHittableCoordinateFallback, true);
225225
});
226226

227227
test('parseMaestroReplayFlow rejects relative runScript paths without source path', () => {
@@ -430,7 +430,7 @@ test('parseMaestroReplayFlow keeps visible-gated runFlow commands for runtime ev
430430
{
431431
command: '__maestroTapOn',
432432
positionals: ['label="Continue" || text="Continue" || id="Continue"'],
433-
flags: { maestro: { allowNonHittableSelectorTap: true } },
433+
flags: { maestro: { allowNonHittableCoordinateFallback: true } },
434434
},
435435
]);
436436
});
@@ -454,7 +454,7 @@ test('parseMaestroReplayFlow accepts launchApp reset options', () => {
454454
'open',
455455
['com.callstack.agentdevicelab'],
456456
{
457-
maestro: { clearState: true },
457+
clearAppState: true,
458458
launchArgs: ['-EXDevMenuIsOnboardingFinished', 'true', '-Example', 'ignored'],
459459
},
460460
],

src/compat/maestro/device-actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function convertLaunchApp(
4242
const shouldRelaunch = !shouldClearState && (value.stopApp === true || launchArgs.length > 0);
4343
return action('open', [appId], {
4444
...(shouldRelaunch ? { relaunch: true } : {}),
45-
...(shouldClearState ? { maestro: { clearState: true } } : {}),
45+
...(shouldClearState ? { clearAppState: true } : {}),
4646
...(launchArgs.length > 0 ? { launchArgs } : {}),
4747
});
4848
}

src/compat/maestro/interactions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ function maestroTapOnFlags(value: unknown): SessionAction['flags'] {
357357
...flags,
358358
maestro: {
359359
...(flags.maestro ?? {}),
360-
allowNonHittableSelectorTap: true,
360+
allowNonHittableCoordinateFallback: true,
361361
},
362362
};
363363
}

src/compat/maestro/replay-flow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ function optimizeInputTextActions(
126126

127127
function clearMaestroNonHittableTap(action: SessionAction): SessionAction {
128128
const maestro = { ...(action.flags?.maestro ?? {}) };
129-
delete maestro.allowNonHittableSelectorTap;
129+
delete maestro.allowNonHittableCoordinateFallback;
130130
return {
131131
...action,
132132
flags: {

src/core/dispatch-context.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ export type BatchStep = {
1111
};
1212

1313
export type MaestroRuntimeFlags = {
14-
allowNonHittableSelectorTap?: boolean;
15-
clearState?: boolean;
14+
allowNonHittableCoordinateFallback?: boolean;
1615
optional?: boolean;
1716
runScriptEnv?: Record<string, string>;
1817
};
1918

2019
export type CommandFlags = Omit<CliFlags, DaemonExcludedCliFlag> & {
2120
batchSteps?: BatchStep[];
21+
clearAppState?: boolean;
2222
launchArgs?: string[];
2323
maestro?: MaestroRuntimeFlags;
2424
replayBackend?: string;
@@ -55,6 +55,6 @@ export type DispatchContext = ScreenshotDispatchFlags & {
5555
key: 'id' | 'label' | 'text' | 'value';
5656
value: string;
5757
raw: string;
58-
allowNonHittableTap?: boolean;
58+
allowNonHittableCoordinateFallback?: boolean;
5959
};
6060
};

src/core/dispatch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,13 @@ async function handleOpenCommand(
236236
if (isDeepLinkTarget(app)) {
237237
throw new AppError(
238238
'INVALID_ARGS',
239-
'Maestro launchApp.clearState requires an app target, not a deep link.',
239+
'Clearing app state requires an app target, not a deep link.',
240240
);
241241
}
242242
if (device.platform !== 'ios' || device.kind !== 'simulator') {
243243
throw new AppError(
244244
'UNSUPPORTED_OPERATION',
245-
'Maestro launchApp.clearState is currently supported only on iOS simulators.',
245+
'Clearing app state is currently supported only on iOS simulators.',
246246
);
247247
}
248248
await clearIosSimulatorAppState(device, app);

src/core/interactor-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export type ScreenshotOptions = {
2929
export type ElementSelectorTapOptions = {
3030
key: 'id' | 'label' | 'text' | 'value';
3131
value: string;
32-
allowNonHittableTap?: boolean;
32+
allowNonHittableCoordinateFallback?: boolean;
3333
};
3434

3535
export type SnapshotOptions = BaseSnapshotOptions & {

src/daemon/__tests__/context.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ test('contextFromFlags forwards scroll pixels from CLI flags', () => {
1414
assert.equal(context.pixels, 240);
1515
});
1616

17-
test('contextFromFlags maps Maestro clearState to generic app-state clearing', () => {
18-
const flags: CommandFlags = { maestro: { clearState: true } };
17+
test('contextFromFlags forwards generic app-state clearing', () => {
18+
const flags: CommandFlags = { clearAppState: true };
1919
const context = contextFromFlags('/tmp/agent-device.log', flags);
2020
assert.equal(context.clearAppState, true);
2121
});

0 commit comments

Comments
 (0)