@deeeed/metamask-harness 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/adapters.js +73 -1
- package/dist/paths.js +7 -0
- package/dist/runner.js +13 -2
- package/library/manifests/extension.action-manifest.json +210 -2
- package/library/manifests/mobile.action-manifest.json +214 -0
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.33.0 - 2026-08-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Expose standard full-surface capture and continuous UI gestures for Mobile and Extension by delegating to the shared native and browser transports.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Upgrade `@farmslot/agent-runtime` to 0.7.0, `@farmslot/protocol` to 0.18.0, and `@farmslot/recipe-harness` to 0.14.0, and add `@farmslot/expo-recipe` 0.7.1 with `agent-device` 0.19.3 for the native UI provider.
|
|
14
|
+
|
|
5
15
|
## 0.32.0 - 2026-08-02
|
|
6
16
|
|
|
7
17
|
### Changed
|
package/dist/adapters.js
CHANGED
|
@@ -6,6 +6,13 @@ import {
|
|
|
6
6
|
import { withExtensionPage } from "../library/actions/extension/platform/cdp.mjs";
|
|
7
7
|
import { bridgeCommand, evalSync, MOBILE_BRIDGE_ERROR_CODES, selectBridgeStatusEntry, simulatorScreenshot } from "../library/actions/mobile/platform/bridge.mjs";
|
|
8
8
|
import { observeNativeUi } from "../library/actions/mobile/platform/observe-ui.mjs";
|
|
9
|
+
const NATIVE_PROVIDER_UI_ACTIONS = /* @__PURE__ */ new Set([
|
|
10
|
+
"ui.swipe",
|
|
11
|
+
"ui.pan",
|
|
12
|
+
"ui.drag",
|
|
13
|
+
"ui.long_press",
|
|
14
|
+
"ui.capture_surface"
|
|
15
|
+
]);
|
|
9
16
|
function sleep(ms) {
|
|
10
17
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
18
|
}
|
|
@@ -480,7 +487,7 @@ function createMetaMaskUiTransport(platform, harness, preparedLiveAdapters) {
|
|
|
480
487
|
return {
|
|
481
488
|
async execute(action) {
|
|
482
489
|
throw new Error(
|
|
483
|
-
`core adapter is headless and cannot execute UI action ${action}.
|
|
490
|
+
`core adapter is headless and cannot execute UI action ${action}. Next: mm-harness actions --matrix`
|
|
484
491
|
);
|
|
485
492
|
}
|
|
486
493
|
};
|
|
@@ -516,10 +523,75 @@ function createMetaMaskUiTransport(platform, harness, preparedLiveAdapters) {
|
|
|
516
523
|
if (live) return live.output;
|
|
517
524
|
throw new Error(`ui.navigate requires library/actions/${platform}/ui/navigate.mjs.`);
|
|
518
525
|
}
|
|
526
|
+
if (platform === "mobile" && NATIVE_PROVIDER_UI_ACTIONS.has(action)) {
|
|
527
|
+
return executeNativeProviderAction(action, node, context, harness.createNativeUiTransport);
|
|
528
|
+
}
|
|
519
529
|
return base.execute(action, action === "ui.wait_for" ? normalizeUiWaitNode(node) : node, context);
|
|
520
530
|
}
|
|
521
531
|
};
|
|
522
532
|
}
|
|
533
|
+
async function executeNativeProviderAction(action, node, context, createTransport) {
|
|
534
|
+
if (!createTransport) {
|
|
535
|
+
throw new Error(
|
|
536
|
+
`${action} requires the MetaMask native UI provider. Next: npm install -g @deeeed/metamask-harness@latest`
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
const platform = mobileNativePlatform(context.env);
|
|
540
|
+
const device = platform === "android" ? context.env.ADB_SERIAL ?? context.env.ANDROID_SERIAL ?? process.env.ADB_SERIAL ?? process.env.ANDROID_SERIAL : context.env.SIM_UDID ?? context.env.IOS_SIMULATOR ?? process.env.SIM_UDID ?? process.env.IOS_SIMULATOR;
|
|
541
|
+
if (!device) {
|
|
542
|
+
throw new Error(
|
|
543
|
+
`${action} requires one selected ${platform} device. Next: mm-harness status --adapter mobile --all-devices --json`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
const app = platform === "android" ? context.env.ANDROID_PACKAGE_ID ?? process.env.ANDROID_PACKAGE_ID : context.env.IOS_BUNDLE_ID ?? process.env.IOS_BUNDLE_ID;
|
|
547
|
+
if (!app) {
|
|
548
|
+
const variable = platform === "android" ? "ANDROID_PACKAGE_ID" : "IOS_BUNDLE_ID";
|
|
549
|
+
throw new Error(
|
|
550
|
+
`${action} requires the selected MetaMask app id. Next: export ${variable}=<installed-app-id>`
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
const session = `mm-harness-${process.pid}-${context.nodeId}`.replace(/[^a-zA-Z0-9._-]/gu, "-");
|
|
554
|
+
let transport;
|
|
555
|
+
try {
|
|
556
|
+
transport = await createTransport({ platform, device, app, session });
|
|
557
|
+
} catch (error) {
|
|
558
|
+
throw new Error(
|
|
559
|
+
`${action} could not start the MetaMask native UI provider. Next: npm install -g @deeeed/metamask-harness@latest`,
|
|
560
|
+
{ cause: error }
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
let executionError;
|
|
564
|
+
let output;
|
|
565
|
+
try {
|
|
566
|
+
output = await transport.execute(action, node, context);
|
|
567
|
+
} catch (error) {
|
|
568
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
569
|
+
executionError = /^Native recipe actions require the optional agent-device provider:/u.test(message) ? new Error(
|
|
570
|
+
`${action} could not start the MetaMask native UI provider. Next: npm install -g @deeeed/metamask-harness@latest`,
|
|
571
|
+
{ cause: error }
|
|
572
|
+
) : error;
|
|
573
|
+
}
|
|
574
|
+
let closeError;
|
|
575
|
+
try {
|
|
576
|
+
await transport.close?.();
|
|
577
|
+
} catch (error) {
|
|
578
|
+
closeError = error;
|
|
579
|
+
}
|
|
580
|
+
if (executionError && closeError) {
|
|
581
|
+
const message = executionError instanceof Error ? executionError.message : String(executionError);
|
|
582
|
+
throw new AggregateError([executionError, closeError], message);
|
|
583
|
+
}
|
|
584
|
+
if (executionError) throw executionError;
|
|
585
|
+
if (closeError) throw closeError;
|
|
586
|
+
return output;
|
|
587
|
+
}
|
|
588
|
+
function mobileNativePlatform(env) {
|
|
589
|
+
if (env.PLATFORM === "android" || env.PLATFORM === "ios") return env.PLATFORM;
|
|
590
|
+
if (env.ADB_SERIAL || env.ANDROID_SERIAL) return "android";
|
|
591
|
+
if (env.SIM_UDID || env.IOS_SIMULATOR) return "ios";
|
|
592
|
+
if (process.env.PLATFORM === "android" || process.env.PLATFORM === "ios") return process.env.PLATFORM;
|
|
593
|
+
return process.env.ADB_SERIAL || process.env.ANDROID_SERIAL ? "android" : "ios";
|
|
594
|
+
}
|
|
523
595
|
function normalizeUiWaitNode(node) {
|
|
524
596
|
if (node.expected !== void 0 || typeof node.visible !== "boolean") return node;
|
|
525
597
|
return { ...node, expected: node.visible ? "visible" : "absent" };
|
package/dist/paths.js
CHANGED
|
@@ -128,6 +128,12 @@ async function importRecipeHarnessRuntimeReactNativeBridge() {
|
|
|
128
128
|
"packages/recipe-harness/src/runtime/react-native-bridge.ts"
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
|
+
async function importMetaMaskNativeUiProvider() {
|
|
132
|
+
return importProtocolPackage(
|
|
133
|
+
"@farmslot/expo-recipe",
|
|
134
|
+
"packages/expo-recipe/src/index.ts"
|
|
135
|
+
);
|
|
136
|
+
}
|
|
131
137
|
async function importRecipeHarnessCli() {
|
|
132
138
|
return importProtocolPackage(
|
|
133
139
|
"@farmslot/recipe-harness/cli",
|
|
@@ -164,6 +170,7 @@ export {
|
|
|
164
170
|
DEFAULT_RECIPE_RUNTIME_DIR,
|
|
165
171
|
assertAdapter,
|
|
166
172
|
extensionIdPath,
|
|
173
|
+
importMetaMaskNativeUiProvider,
|
|
167
174
|
importRecipeHarness,
|
|
168
175
|
importRecipeHarnessAppLifecycle,
|
|
169
176
|
importRecipeHarnessCli,
|
package/dist/runner.js
CHANGED
|
@@ -12,7 +12,14 @@ import {
|
|
|
12
12
|
prepareLiveAdapterScript
|
|
13
13
|
} from "./live-adapter-contract.js";
|
|
14
14
|
import { createMetaMaskRecordingTargetProvider } from "./recording-target.js";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
importMetaMaskNativeUiProvider,
|
|
17
|
+
importRecipeHarness,
|
|
18
|
+
importRecipeHarnessAppLifecycle,
|
|
19
|
+
importRecipeHarnessRuntimeCdp,
|
|
20
|
+
importRecipeHarnessRuntimeReactNativeBridge,
|
|
21
|
+
runnerDir
|
|
22
|
+
} from "./paths.js";
|
|
16
23
|
const OFFICIAL_ACTIONS = new Set(OFFICIAL_RECIPE_ACTIONS);
|
|
17
24
|
async function createMetaMaskMobileRunner(options = {}) {
|
|
18
25
|
return createMetaMaskRunner(
|
|
@@ -51,7 +58,11 @@ async function createMetaMaskRunner(adapter, actionManifest, options = {}) {
|
|
|
51
58
|
actions: actions.filter((action) => !projectOwnedOfficialActions.has(action)),
|
|
52
59
|
transport: createMetaMaskUiTransport(adapter, {
|
|
53
60
|
createCdpWebUiTransport,
|
|
54
|
-
createReactNativeBridgeUiTransport
|
|
61
|
+
createReactNativeBridgeUiTransport,
|
|
62
|
+
async createNativeUiTransport(options2) {
|
|
63
|
+
const { createAgentDeviceUiTransport } = await importMetaMaskNativeUiProvider();
|
|
64
|
+
return createAgentDeviceUiTransport(options2);
|
|
65
|
+
}
|
|
55
66
|
}, preparedLiveAdapters)
|
|
56
67
|
});
|
|
57
68
|
const existing = new Set([...core, ...ui].map((entry) => entry.action));
|
|
@@ -664,6 +664,183 @@
|
|
|
664
664
|
"additionalProperties": false
|
|
665
665
|
}
|
|
666
666
|
},
|
|
667
|
+
"ui.swipe": {
|
|
668
|
+
"description": "Swipe from a test-id target or screen coordinates in one cardinal direction through the shared browser UI transport.",
|
|
669
|
+
"schema": {
|
|
670
|
+
"type": "object",
|
|
671
|
+
"properties": {
|
|
672
|
+
"target": {
|
|
673
|
+
"type": ["string", "object"],
|
|
674
|
+
"properties": {
|
|
675
|
+
"x": { "type": "number" },
|
|
676
|
+
"y": { "type": "number" }
|
|
677
|
+
},
|
|
678
|
+
"required": ["x", "y"],
|
|
679
|
+
"additionalProperties": false
|
|
680
|
+
},
|
|
681
|
+
"direction": {
|
|
682
|
+
"type": "string",
|
|
683
|
+
"enum": ["up", "down", "left", "right"]
|
|
684
|
+
},
|
|
685
|
+
"distance": { "type": "number", "minimum": 1 },
|
|
686
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
687
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
688
|
+
"settle": { "type": "boolean" }
|
|
689
|
+
},
|
|
690
|
+
"required": ["target", "direction", "distance", "duration_ms"],
|
|
691
|
+
"additionalProperties": false
|
|
692
|
+
},
|
|
693
|
+
"examples": [
|
|
694
|
+
{
|
|
695
|
+
"action": "ui.swipe",
|
|
696
|
+
"target": "example-scrollable",
|
|
697
|
+
"direction": "up",
|
|
698
|
+
"distance": 240,
|
|
699
|
+
"duration_ms": 300,
|
|
700
|
+
"intent": "Swipe the requested visible surface.",
|
|
701
|
+
"next": "done"
|
|
702
|
+
}
|
|
703
|
+
]
|
|
704
|
+
},
|
|
705
|
+
"ui.pan": {
|
|
706
|
+
"description": "Pan through a continuous pointer path from a test-id target or screen coordinates through the shared browser UI transport.",
|
|
707
|
+
"schema": {
|
|
708
|
+
"type": "object",
|
|
709
|
+
"properties": {
|
|
710
|
+
"target": {
|
|
711
|
+
"type": ["string", "object"],
|
|
712
|
+
"properties": {
|
|
713
|
+
"x": { "type": "number" },
|
|
714
|
+
"y": { "type": "number" }
|
|
715
|
+
},
|
|
716
|
+
"required": ["x", "y"],
|
|
717
|
+
"additionalProperties": false
|
|
718
|
+
},
|
|
719
|
+
"path": {
|
|
720
|
+
"type": "array",
|
|
721
|
+
"minItems": 1,
|
|
722
|
+
"items": {
|
|
723
|
+
"type": "object",
|
|
724
|
+
"properties": {
|
|
725
|
+
"x": { "type": "number" },
|
|
726
|
+
"y": { "type": "number" }
|
|
727
|
+
},
|
|
728
|
+
"required": ["x", "y"],
|
|
729
|
+
"additionalProperties": false
|
|
730
|
+
}
|
|
731
|
+
},
|
|
732
|
+
"delta": {
|
|
733
|
+
"type": "object",
|
|
734
|
+
"properties": {
|
|
735
|
+
"x": { "type": "number" },
|
|
736
|
+
"y": { "type": "number" }
|
|
737
|
+
},
|
|
738
|
+
"required": ["x", "y"],
|
|
739
|
+
"additionalProperties": false
|
|
740
|
+
},
|
|
741
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
742
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
743
|
+
"settle": { "type": "boolean" }
|
|
744
|
+
},
|
|
745
|
+
"required": ["target", "duration_ms"],
|
|
746
|
+
"additionalProperties": false
|
|
747
|
+
},
|
|
748
|
+
"examples": [
|
|
749
|
+
{
|
|
750
|
+
"action": "ui.pan",
|
|
751
|
+
"target": "example-surface",
|
|
752
|
+
"path": [{ "x": 40, "y": 10 }, { "x": 80, "y": 20 }],
|
|
753
|
+
"duration_ms": 400,
|
|
754
|
+
"intent": "Pan through the requested pointer path.",
|
|
755
|
+
"next": "done"
|
|
756
|
+
}
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
"ui.drag": {
|
|
760
|
+
"description": "Drag a test-id target or screen coordinate through the shared browser UI transport.",
|
|
761
|
+
"schema": {
|
|
762
|
+
"type": "object",
|
|
763
|
+
"properties": {
|
|
764
|
+
"target": {
|
|
765
|
+
"type": ["string", "object"],
|
|
766
|
+
"properties": {
|
|
767
|
+
"x": { "type": "number" },
|
|
768
|
+
"y": { "type": "number" }
|
|
769
|
+
},
|
|
770
|
+
"required": ["x", "y"],
|
|
771
|
+
"additionalProperties": false
|
|
772
|
+
},
|
|
773
|
+
"path": {
|
|
774
|
+
"type": "array",
|
|
775
|
+
"minItems": 1,
|
|
776
|
+
"items": {
|
|
777
|
+
"type": "object",
|
|
778
|
+
"properties": {
|
|
779
|
+
"x": { "type": "number" },
|
|
780
|
+
"y": { "type": "number" }
|
|
781
|
+
},
|
|
782
|
+
"required": ["x", "y"],
|
|
783
|
+
"additionalProperties": false
|
|
784
|
+
}
|
|
785
|
+
},
|
|
786
|
+
"delta": {
|
|
787
|
+
"type": "object",
|
|
788
|
+
"properties": {
|
|
789
|
+
"x": { "type": "number" },
|
|
790
|
+
"y": { "type": "number" }
|
|
791
|
+
},
|
|
792
|
+
"required": ["x", "y"],
|
|
793
|
+
"additionalProperties": false
|
|
794
|
+
},
|
|
795
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
796
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
797
|
+
"settle": { "type": "boolean" }
|
|
798
|
+
},
|
|
799
|
+
"required": ["target", "duration_ms"],
|
|
800
|
+
"additionalProperties": false
|
|
801
|
+
},
|
|
802
|
+
"examples": [
|
|
803
|
+
{
|
|
804
|
+
"action": "ui.drag",
|
|
805
|
+
"target": "example-slider",
|
|
806
|
+
"delta": { "x": 120, "y": 0 },
|
|
807
|
+
"duration_ms": 500,
|
|
808
|
+
"intent": "Drag the requested control to a new value.",
|
|
809
|
+
"next": "done"
|
|
810
|
+
}
|
|
811
|
+
]
|
|
812
|
+
},
|
|
813
|
+
"ui.long_press": {
|
|
814
|
+
"description": "Hold a test-id target or screen coordinate through the shared browser UI transport.",
|
|
815
|
+
"schema": {
|
|
816
|
+
"type": "object",
|
|
817
|
+
"properties": {
|
|
818
|
+
"target": {
|
|
819
|
+
"type": ["string", "object"],
|
|
820
|
+
"properties": {
|
|
821
|
+
"x": { "type": "number" },
|
|
822
|
+
"y": { "type": "number" }
|
|
823
|
+
},
|
|
824
|
+
"required": ["x", "y"],
|
|
825
|
+
"additionalProperties": false
|
|
826
|
+
},
|
|
827
|
+
"hold_ms": { "type": "integer", "minimum": 1 },
|
|
828
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
829
|
+
"settle": { "type": "boolean" }
|
|
830
|
+
},
|
|
831
|
+
"required": ["target", "hold_ms"],
|
|
832
|
+
"additionalProperties": false
|
|
833
|
+
},
|
|
834
|
+
"examples": [
|
|
835
|
+
{
|
|
836
|
+
"action": "ui.long_press",
|
|
837
|
+
"target": "example-control",
|
|
838
|
+
"hold_ms": 700,
|
|
839
|
+
"intent": "Hold the requested visible control.",
|
|
840
|
+
"next": "done"
|
|
841
|
+
}
|
|
842
|
+
]
|
|
843
|
+
},
|
|
667
844
|
"ui.wait_for": {
|
|
668
845
|
"description": "Wait for a UI condition through the Extension CDP adapter.",
|
|
669
846
|
"schema": {
|
|
@@ -763,6 +940,27 @@
|
|
|
763
940
|
"additionalProperties": false
|
|
764
941
|
}
|
|
765
942
|
},
|
|
943
|
+
"ui.capture_surface": {
|
|
944
|
+
"description": "Capture the complete current browser page as one registered PNG while leaving ui.screenshot viewport-only.",
|
|
945
|
+
"schema": {
|
|
946
|
+
"type": "object",
|
|
947
|
+
"properties": {
|
|
948
|
+
"path": { "type": "string" },
|
|
949
|
+
"label": { "type": "string" },
|
|
950
|
+
"category": { "type": "string" },
|
|
951
|
+
"timeout_ms": { "type": "number" }
|
|
952
|
+
},
|
|
953
|
+
"additionalProperties": false
|
|
954
|
+
},
|
|
955
|
+
"examples": [
|
|
956
|
+
{
|
|
957
|
+
"action": "ui.capture_surface",
|
|
958
|
+
"path": "screenshots/full-page.png",
|
|
959
|
+
"intent": "Preserve the complete page context for human review.",
|
|
960
|
+
"next": "done"
|
|
961
|
+
}
|
|
962
|
+
]
|
|
963
|
+
},
|
|
766
964
|
"app.status": {
|
|
767
965
|
"description": "Report the adapter's static status — platform, project root, resolved checkout shape, and headless compatibility mode (no live route or account).",
|
|
768
966
|
"examples": [
|
|
@@ -2982,8 +3180,13 @@
|
|
|
2982
3180
|
"ui.key_press",
|
|
2983
3181
|
"ui.set_input",
|
|
2984
3182
|
"ui.scroll",
|
|
3183
|
+
"ui.swipe",
|
|
3184
|
+
"ui.pan",
|
|
3185
|
+
"ui.drag",
|
|
3186
|
+
"ui.long_press",
|
|
2985
3187
|
"ui.wait_for",
|
|
2986
|
-
"ui.screenshot"
|
|
3188
|
+
"ui.screenshot",
|
|
3189
|
+
"ui.capture_surface"
|
|
2987
3190
|
]
|
|
2988
3191
|
},
|
|
2989
3192
|
{
|
|
@@ -2995,8 +3198,13 @@
|
|
|
2995
3198
|
"ui.key_press",
|
|
2996
3199
|
"ui.set_input",
|
|
2997
3200
|
"ui.scroll",
|
|
3201
|
+
"ui.swipe",
|
|
3202
|
+
"ui.pan",
|
|
3203
|
+
"ui.drag",
|
|
3204
|
+
"ui.long_press",
|
|
2998
3205
|
"ui.wait_for",
|
|
2999
|
-
"ui.screenshot"
|
|
3206
|
+
"ui.screenshot",
|
|
3207
|
+
"ui.capture_surface"
|
|
3000
3208
|
]
|
|
3001
3209
|
}
|
|
3002
3210
|
]
|
|
@@ -675,6 +675,185 @@
|
|
|
675
675
|
"additionalProperties": false
|
|
676
676
|
}
|
|
677
677
|
},
|
|
678
|
+
"ui.swipe": {
|
|
679
|
+
"description": "Swipe from a test-id target or screen coordinates in one cardinal direction through the shared native UI provider.",
|
|
680
|
+
"schema": {
|
|
681
|
+
"type": "object",
|
|
682
|
+
"properties": {
|
|
683
|
+
"target": {
|
|
684
|
+
"type": ["string", "object"],
|
|
685
|
+
"properties": {
|
|
686
|
+
"x": { "type": "number" },
|
|
687
|
+
"y": { "type": "number" }
|
|
688
|
+
},
|
|
689
|
+
"required": ["x", "y"],
|
|
690
|
+
"additionalProperties": false
|
|
691
|
+
},
|
|
692
|
+
"direction": {
|
|
693
|
+
"type": "string",
|
|
694
|
+
"enum": ["up", "down", "left", "right"]
|
|
695
|
+
},
|
|
696
|
+
"distance": { "type": "number", "minimum": 1 },
|
|
697
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
698
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
699
|
+
"settle": { "type": "boolean" }
|
|
700
|
+
},
|
|
701
|
+
"required": ["target", "direction", "distance", "duration_ms"],
|
|
702
|
+
"additionalProperties": false
|
|
703
|
+
},
|
|
704
|
+
"examples": [
|
|
705
|
+
{
|
|
706
|
+
"action": "ui.swipe",
|
|
707
|
+
"target": "example-scrollable",
|
|
708
|
+
"direction": "up",
|
|
709
|
+
"distance": 240,
|
|
710
|
+
"duration_ms": 300,
|
|
711
|
+
"intent": "Swipe the requested visible surface.",
|
|
712
|
+
"next": "done"
|
|
713
|
+
}
|
|
714
|
+
]
|
|
715
|
+
},
|
|
716
|
+
"ui.pan": {
|
|
717
|
+
"description": "Pan from a test-id target or screen coordinates through the shared native UI provider.",
|
|
718
|
+
"schema": {
|
|
719
|
+
"type": "object",
|
|
720
|
+
"properties": {
|
|
721
|
+
"target": {
|
|
722
|
+
"type": ["string", "object"],
|
|
723
|
+
"properties": {
|
|
724
|
+
"x": { "type": "number" },
|
|
725
|
+
"y": { "type": "number" }
|
|
726
|
+
},
|
|
727
|
+
"required": ["x", "y"],
|
|
728
|
+
"additionalProperties": false
|
|
729
|
+
},
|
|
730
|
+
"path": {
|
|
731
|
+
"type": "array",
|
|
732
|
+
"minItems": 1,
|
|
733
|
+
"maxItems": 1,
|
|
734
|
+
"items": {
|
|
735
|
+
"type": "object",
|
|
736
|
+
"properties": {
|
|
737
|
+
"x": { "type": "number" },
|
|
738
|
+
"y": { "type": "number" }
|
|
739
|
+
},
|
|
740
|
+
"required": ["x", "y"],
|
|
741
|
+
"additionalProperties": false
|
|
742
|
+
}
|
|
743
|
+
},
|
|
744
|
+
"delta": {
|
|
745
|
+
"type": "object",
|
|
746
|
+
"properties": {
|
|
747
|
+
"x": { "type": "number" },
|
|
748
|
+
"y": { "type": "number" }
|
|
749
|
+
},
|
|
750
|
+
"required": ["x", "y"],
|
|
751
|
+
"additionalProperties": false
|
|
752
|
+
},
|
|
753
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
754
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
755
|
+
"settle": { "type": "boolean" }
|
|
756
|
+
},
|
|
757
|
+
"required": ["target", "duration_ms"],
|
|
758
|
+
"additionalProperties": false
|
|
759
|
+
},
|
|
760
|
+
"examples": [
|
|
761
|
+
{
|
|
762
|
+
"action": "ui.pan",
|
|
763
|
+
"target": "example-surface",
|
|
764
|
+
"path": [{ "x": 80, "y": 20 }],
|
|
765
|
+
"duration_ms": 400,
|
|
766
|
+
"intent": "Pan through the requested pointer path.",
|
|
767
|
+
"next": "done"
|
|
768
|
+
}
|
|
769
|
+
]
|
|
770
|
+
},
|
|
771
|
+
"ui.drag": {
|
|
772
|
+
"description": "Drag a test-id target or screen coordinate through the shared native UI provider.",
|
|
773
|
+
"schema": {
|
|
774
|
+
"type": "object",
|
|
775
|
+
"properties": {
|
|
776
|
+
"target": {
|
|
777
|
+
"type": ["string", "object"],
|
|
778
|
+
"properties": {
|
|
779
|
+
"x": { "type": "number" },
|
|
780
|
+
"y": { "type": "number" }
|
|
781
|
+
},
|
|
782
|
+
"required": ["x", "y"],
|
|
783
|
+
"additionalProperties": false
|
|
784
|
+
},
|
|
785
|
+
"path": {
|
|
786
|
+
"type": "array",
|
|
787
|
+
"minItems": 1,
|
|
788
|
+
"maxItems": 1,
|
|
789
|
+
"items": {
|
|
790
|
+
"type": "object",
|
|
791
|
+
"properties": {
|
|
792
|
+
"x": { "type": "number" },
|
|
793
|
+
"y": { "type": "number" }
|
|
794
|
+
},
|
|
795
|
+
"required": ["x", "y"],
|
|
796
|
+
"additionalProperties": false
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
"delta": {
|
|
800
|
+
"type": "object",
|
|
801
|
+
"properties": {
|
|
802
|
+
"x": { "type": "number" },
|
|
803
|
+
"y": { "type": "number" }
|
|
804
|
+
},
|
|
805
|
+
"required": ["x", "y"],
|
|
806
|
+
"additionalProperties": false
|
|
807
|
+
},
|
|
808
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
809
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
810
|
+
"settle": { "type": "boolean" }
|
|
811
|
+
},
|
|
812
|
+
"required": ["target", "duration_ms"],
|
|
813
|
+
"additionalProperties": false
|
|
814
|
+
},
|
|
815
|
+
"examples": [
|
|
816
|
+
{
|
|
817
|
+
"action": "ui.drag",
|
|
818
|
+
"target": "example-slider",
|
|
819
|
+
"delta": { "x": 120, "y": 0 },
|
|
820
|
+
"duration_ms": 500,
|
|
821
|
+
"intent": "Drag the requested control to a new value.",
|
|
822
|
+
"next": "done"
|
|
823
|
+
}
|
|
824
|
+
]
|
|
825
|
+
},
|
|
826
|
+
"ui.long_press": {
|
|
827
|
+
"description": "Hold a test-id target or screen coordinate through the shared native UI provider.",
|
|
828
|
+
"schema": {
|
|
829
|
+
"type": "object",
|
|
830
|
+
"properties": {
|
|
831
|
+
"target": {
|
|
832
|
+
"type": ["string", "object"],
|
|
833
|
+
"properties": {
|
|
834
|
+
"x": { "type": "number" },
|
|
835
|
+
"y": { "type": "number" }
|
|
836
|
+
},
|
|
837
|
+
"required": ["x", "y"],
|
|
838
|
+
"additionalProperties": false
|
|
839
|
+
},
|
|
840
|
+
"hold_ms": { "type": "integer", "minimum": 1 },
|
|
841
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
842
|
+
"settle": { "type": "boolean" }
|
|
843
|
+
},
|
|
844
|
+
"required": ["target", "hold_ms"],
|
|
845
|
+
"additionalProperties": false
|
|
846
|
+
},
|
|
847
|
+
"examples": [
|
|
848
|
+
{
|
|
849
|
+
"action": "ui.long_press",
|
|
850
|
+
"target": "example-control",
|
|
851
|
+
"hold_ms": 700,
|
|
852
|
+
"intent": "Hold the requested visible control.",
|
|
853
|
+
"next": "done"
|
|
854
|
+
}
|
|
855
|
+
]
|
|
856
|
+
},
|
|
678
857
|
"ui.wait_for": {
|
|
679
858
|
"description": "Wait for a mounted React Native testID/test_id. Optional text validates text returned by that testID; text alone is not supported on Mobile.",
|
|
680
859
|
"schema": {
|
|
@@ -781,6 +960,31 @@
|
|
|
781
960
|
"additionalProperties": false
|
|
782
961
|
}
|
|
783
962
|
},
|
|
963
|
+
"ui.capture_surface": {
|
|
964
|
+
"description": "Capture the complete current native scroll surface as one registered PNG while leaving ui.screenshot viewport-only.",
|
|
965
|
+
"schema": {
|
|
966
|
+
"type": "object",
|
|
967
|
+
"properties": {
|
|
968
|
+
"path": { "type": "string" },
|
|
969
|
+
"label": { "type": "string" },
|
|
970
|
+
"surface_test_id": { "type": "string" },
|
|
971
|
+
"until_test_id": { "type": "string" },
|
|
972
|
+
"max_scrolls": { "type": "integer", "minimum": 1 },
|
|
973
|
+
"restore_position": { "type": "boolean" }
|
|
974
|
+
},
|
|
975
|
+
"additionalProperties": false
|
|
976
|
+
},
|
|
977
|
+
"examples": [
|
|
978
|
+
{
|
|
979
|
+
"action": "ui.capture_surface",
|
|
980
|
+
"path": "screenshots/full-screen.png",
|
|
981
|
+
"surface_test_id": "screen-scroll-surface",
|
|
982
|
+
"until_test_id": "screen-bottom",
|
|
983
|
+
"intent": "Preserve the complete scrollable context for human review.",
|
|
984
|
+
"next": "done"
|
|
985
|
+
}
|
|
986
|
+
]
|
|
987
|
+
},
|
|
784
988
|
"app.lifecycle": {
|
|
785
989
|
"description": "Drive outer mobile app lifecycle for deterministic performance start states without rebuilding: foreground/launch, background, terminate, or restart the installed app.",
|
|
786
990
|
"examples": [
|
|
@@ -3101,7 +3305,12 @@
|
|
|
3101
3305
|
"metamask.deeplink.open",
|
|
3102
3306
|
"ui.navigate",
|
|
3103
3307
|
"ui.press",
|
|
3308
|
+
"ui.swipe",
|
|
3309
|
+
"ui.pan",
|
|
3310
|
+
"ui.drag",
|
|
3311
|
+
"ui.long_press",
|
|
3104
3312
|
"ui.screenshot",
|
|
3313
|
+
"ui.capture_surface",
|
|
3105
3314
|
"ui.scroll",
|
|
3106
3315
|
"ui.set_input",
|
|
3107
3316
|
"ui.wait_for"
|
|
@@ -3113,7 +3322,12 @@
|
|
|
3113
3322
|
"metamask.deeplink.open",
|
|
3114
3323
|
"ui.navigate",
|
|
3115
3324
|
"ui.press",
|
|
3325
|
+
"ui.swipe",
|
|
3326
|
+
"ui.pan",
|
|
3327
|
+
"ui.drag",
|
|
3328
|
+
"ui.long_press",
|
|
3116
3329
|
"ui.screenshot",
|
|
3330
|
+
"ui.capture_surface",
|
|
3117
3331
|
"ui.scroll",
|
|
3118
3332
|
"ui.set_input",
|
|
3119
3333
|
"ui.wait_for"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deeeed/metamask-harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mm-harness": "bin/mm-harness"
|
|
@@ -20,10 +20,12 @@
|
|
|
20
20
|
"check:syntax": "find . -name '*.mjs' -print0 | xargs -0 -n1 node --check"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@farmslot/agent-runtime": "0.
|
|
23
|
+
"@farmslot/agent-runtime": "0.7.0",
|
|
24
|
+
"@farmslot/expo-recipe": "0.7.1",
|
|
24
25
|
"@farmslot/handoff": "^0.3.1",
|
|
25
|
-
"@farmslot/protocol": "0.
|
|
26
|
-
"@farmslot/recipe-harness": "0.
|
|
26
|
+
"@farmslot/protocol": "0.18.0",
|
|
27
|
+
"@farmslot/recipe-harness": "0.14.0",
|
|
28
|
+
"agent-device": "0.19.3",
|
|
27
29
|
"commander": "^12.0.0",
|
|
28
30
|
"es-module-lexer": "2.3.1",
|
|
29
31
|
"esbuild": "0.28.1",
|