Skip to content

Commit 222f753

Browse files
committed
feat: group gesture commands
1 parent 52a747d commit 222f753

12 files changed

Lines changed: 309 additions & 178 deletions

File tree

examples/test-app/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ pnpm test-app:replay:android
8888

8989
These run the `.ad` replay suite in `examples/test-app/replays`.
9090

91-
`gesture-lab.ad` is iOS-only and verifies `pan`, `fling`, `pinch`, and
92-
`rotate-gesture` against the gesture metrics rendered by the Home screen.
91+
`gesture-lab.ad` is iOS-only and verifies `gesture pan`, `gesture fling`,
92+
`gesture pinch`, and `gesture rotate` against the gesture metrics rendered by
93+
the Home screen.
9394

9495
To target a specific iOS simulator or an installed Expo development build, run the
9596
underlying command directly so global flags stay before replay inputs:

examples/test-app/replays/gesture-lab.ad

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,34 @@ env APP_URL=""
66
open "${APP_TARGET}" --relaunch --launch-url "${APP_URL}"
77
wait "Gesture lab" 30000
88

9-
fling left 195 443 180
9+
gesture fling left 195 443 180
1010
wait "fling 1" 5000
1111

12-
fling right 195 443 180
12+
gesture fling right 195 443 180
1313
wait "fling 2" 5000
1414

15-
fling up 195 443 80 80
15+
gesture fling up 195 443 80 80
1616
wait "fling 3" 5000
1717

18-
fling down 195 443 80 80
18+
gesture fling down 195 443 80 80
1919
wait "fling 4" 5000
2020

21-
pan 195 443 -80 0
21+
gesture pan 195 443 -80 0
2222
wait "x -" 5000
2323

24-
pan 195 443 160 0
24+
gesture pan 195 443 160 0
2525
wait "x 72" 5000
2626

27-
pan 195 443 0 -80
27+
gesture pan 195 443 0 -80
2828
wait "y -" 5000
2929

30-
pan 195 443 0 160
30+
gesture pan 195 443 0 160
3131
wait "y 56" 5000
3232

33-
pinch 1.25 195 443
33+
gesture pinch 1.25 195 443
3434
wait "pinch changed yes" 5000
3535

36-
rotate-gesture 35 195 443
36+
gesture rotate 35 195 443
3737
wait "rotate changed yes" 5000
3838

3939
close

src/cli/commands/generic.ts

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -111,23 +111,11 @@ const genericClientCommandRunners = {
111111
pauseMs: flags.pauseMs,
112112
pattern: flags.pattern,
113113
}),
114-
pan: ({ client, positionals, flags }) =>
115-
client.interactions.pan({
116-
...buildSelectionOptions(flags),
117-
x: Number(positionals[0]),
118-
y: Number(positionals[1]),
119-
dx: Number(positionals[2]),
120-
dy: Number(positionals[3]),
121-
durationMs: optionalNumber(positionals[4]),
122-
}),
123-
fling: ({ client, positionals, flags }) =>
124-
client.interactions.fling({
125-
...buildSelectionOptions(flags),
126-
direction: readGestureDirection(positionals[0], 'fling'),
127-
x: Number(positionals[1]),
128-
y: Number(positionals[2]),
129-
distance: optionalNumber(positionals[3]),
130-
durationMs: optionalNumber(positionals[4]),
114+
gesture: ({ client, positionals, flags }) =>
115+
runGestureCommand({
116+
client,
117+
positionals,
118+
flags,
131119
}),
132120
focus: ({ client, positionals, flags }) =>
133121
client.interactions.focus({
@@ -153,21 +141,6 @@ const genericClientCommandRunners = {
153141
amount: optionalNumber(positionals[1]),
154142
pixels: flags.pixels,
155143
}),
156-
pinch: ({ client, positionals, flags }) =>
157-
client.interactions.pinch({
158-
...buildSelectionOptions(flags),
159-
scale: Number(positionals[0]),
160-
x: optionalNumber(positionals[1]),
161-
y: optionalNumber(positionals[2]),
162-
}),
163-
'rotate-gesture': ({ client, positionals, flags }) =>
164-
client.interactions.rotateGesture({
165-
...buildSelectionOptions(flags),
166-
degrees: Number(positionals[0]),
167-
x: optionalNumber(positionals[1]),
168-
y: optionalNumber(positionals[2]),
169-
velocity: optionalNumber(positionals[3]),
170-
}),
171144
'trigger-app-event': ({ client, positionals, flags }) =>
172145
client.apps.triggerEvent({
173146
...buildSelectionOptions(flags),
@@ -218,6 +191,53 @@ const genericClientCommandRunners = {
218191
client.settings.update(settingsCommandCodec.decode(positionals, flags)),
219192
} satisfies Partial<Record<PublicCommandName, GenericClientCommandRunner>>;
220193

194+
function runGestureCommand(params: {
195+
client: AgentDeviceClient;
196+
positionals: string[];
197+
flags: CliFlags;
198+
}): Promise<CommandRequestResult> {
199+
const { client, positionals, flags } = params;
200+
const subcommand = required(positionals[0], 'gesture requires subcommand');
201+
const args = positionals.slice(1);
202+
switch (subcommand) {
203+
case 'pan':
204+
return client.interactions.pan({
205+
...buildSelectionOptions(flags),
206+
x: Number(args[0]),
207+
y: Number(args[1]),
208+
dx: Number(args[2]),
209+
dy: Number(args[3]),
210+
durationMs: optionalNumber(args[4]),
211+
});
212+
case 'fling':
213+
return client.interactions.fling({
214+
...buildSelectionOptions(flags),
215+
direction: readGestureDirection(args[0], 'gesture fling'),
216+
x: Number(args[1]),
217+
y: Number(args[2]),
218+
distance: optionalNumber(args[3]),
219+
durationMs: optionalNumber(args[4]),
220+
});
221+
case 'pinch':
222+
return client.interactions.pinch({
223+
...buildSelectionOptions(flags),
224+
scale: Number(args[0]),
225+
x: optionalNumber(args[1]),
226+
y: optionalNumber(args[2]),
227+
});
228+
case 'rotate':
229+
return client.interactions.rotateGesture({
230+
...buildSelectionOptions(flags),
231+
degrees: Number(args[0]),
232+
x: optionalNumber(args[1]),
233+
y: optionalNumber(args[2]),
234+
velocity: optionalNumber(args[3]),
235+
});
236+
default:
237+
throw new AppError('INVALID_ARGS', 'gesture requires one of: pan, fling, pinch, rotate');
238+
}
239+
}
240+
221241
export const genericClientCommandHandlers = Object.fromEntries(
222242
Object.entries(genericClientCommandRunners).map(([command, run]) => [
223243
command,

src/client.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,9 @@ export function createAgentDeviceClient(
333333
),
334334
pan: async (options) =>
335335
await executeCommandRequest(
336-
PUBLIC_COMMANDS.pan,
336+
PUBLIC_COMMANDS.gesture,
337337
[
338+
'pan',
338339
String(options.x),
339340
String(options.y),
340341
String(options.dx),
@@ -347,8 +348,9 @@ export function createAgentDeviceClient(
347348
const distance =
348349
options.durationMs !== undefined ? (options.distance ?? 180) : options.distance;
349350
return await executeCommandRequest(
350-
PUBLIC_COMMANDS.fling,
351+
PUBLIC_COMMANDS.gesture,
351352
[
353+
'fling',
352354
options.direction,
353355
String(options.x),
354356
String(options.y),
@@ -384,15 +386,21 @@ export function createAgentDeviceClient(
384386
),
385387
pinch: async (options) =>
386388
await executeCommandRequest(
387-
PUBLIC_COMMANDS.pinch,
388-
[String(options.scale), ...optionalNumber(options.x), ...optionalNumber(options.y)],
389+
PUBLIC_COMMANDS.gesture,
390+
[
391+
'pinch',
392+
String(options.scale),
393+
...optionalNumber(options.x),
394+
...optionalNumber(options.y),
395+
],
389396
options,
390397
),
391398
rotateGesture: async (options) => {
392399
const center = options.x !== undefined || options.y !== undefined;
393400
return await executeCommandRequest(
394-
PUBLIC_COMMANDS.rotateGesture,
401+
PUBLIC_COMMANDS.gesture,
395402
[
403+
'rotate',
396404
String(options.degrees),
397405
...(center ? [String(options.x), String(options.y)] : []),
398406
...optionalNumber(options.velocity),

src/command-catalog.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export const PUBLIC_COMMANDS = {
1313
diff: 'diff',
1414
fill: 'fill',
1515
find: 'find',
16-
fling: 'fling',
1716
focus: 'focus',
17+
gesture: 'gesture',
1818
get: 'get',
1919
home: 'home',
2020
install: 'install',
@@ -25,17 +25,14 @@ export const PUBLIC_COMMANDS = {
2525
longPress: 'longpress',
2626
network: 'network',
2727
open: 'open',
28-
pan: 'pan',
2928
perf: 'perf',
30-
pinch: 'pinch',
3129
press: 'press',
3230
push: 'push',
3331
record: 'record',
3432
reactNative: 'react-native',
3533
reinstall: 'reinstall',
3634
replay: 'replay',
3735
rotate: 'rotate',
38-
rotateGesture: 'rotate-gesture',
3936
scroll: 'scroll',
4037
screenshot: 'screenshot',
4138
settings: 'settings',
@@ -91,19 +88,17 @@ export const DAEMON_COMMAND_GROUPS = {
9188
PUBLIC_COMMANDS.diff,
9289
PUBLIC_COMMANDS.fill,
9390
PUBLIC_COMMANDS.find,
94-
PUBLIC_COMMANDS.fling,
91+
PUBLIC_COMMANDS.gesture,
9592
PUBLIC_COMMANDS.get,
9693
PUBLIC_COMMANDS.home,
9794
PUBLIC_COMMANDS.is,
9895
PUBLIC_COMMANDS.keyboard,
9996
PUBLIC_COMMANDS.longPress,
100-
PUBLIC_COMMANDS.pan,
101-
PUBLIC_COMMANDS.pinch,
97+
'pinch',
10298
PUBLIC_COMMANDS.press,
10399
PUBLIC_COMMANDS.record,
104100
PUBLIC_COMMANDS.reactNative,
105101
PUBLIC_COMMANDS.rotate,
106-
PUBLIC_COMMANDS.rotateGesture,
107102
PUBLIC_COMMANDS.screenshot,
108103
PUBLIC_COMMANDS.scroll,
109104
PUBLIC_COMMANDS.settings,

0 commit comments

Comments
 (0)