swipium 1.0.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/appMap/automationLink.js +74 -0
- package/dist/appMap/automationLink.js.map +1 -0
- package/dist/appMap/build.js +193 -0
- package/dist/appMap/build.js.map +1 -0
- package/dist/appMap/codeIndex.js +73 -0
- package/dist/appMap/codeIndex.js.map +1 -0
- package/dist/appMap/featureModel.js +83 -0
- package/dist/appMap/featureModel.js.map +1 -0
- package/dist/appMap/firstRunApply.js +131 -0
- package/dist/appMap/firstRunApply.js.map +1 -0
- package/dist/appMap/fsWalk.js +75 -0
- package/dist/appMap/fsWalk.js.map +1 -0
- package/dist/appMap/issues.js +227 -0
- package/dist/appMap/issues.js.map +1 -0
- package/dist/appMap/migrations.js +87 -0
- package/dist/appMap/migrations.js.map +1 -0
- package/dist/appMap/prelaunch.js +66 -0
- package/dist/appMap/prelaunch.js.map +1 -0
- package/dist/appMap/projectRegistry.js +70 -0
- package/dist/appMap/projectRegistry.js.map +1 -0
- package/dist/appMap/provenance.js +52 -0
- package/dist/appMap/provenance.js.map +1 -0
- package/dist/appMap/query.js +118 -0
- package/dist/appMap/query.js.map +1 -0
- package/dist/appMap/runtimeMerge.js +207 -0
- package/dist/appMap/runtimeMerge.js.map +1 -0
- package/dist/appMap/schema.js +65 -0
- package/dist/appMap/schema.js.map +1 -0
- package/dist/appMap/screenMatch.js +75 -0
- package/dist/appMap/screenMatch.js.map +1 -0
- package/dist/appMap/staticScan.js +614 -0
- package/dist/appMap/staticScan.js.map +1 -0
- package/dist/appMap/store.js +173 -0
- package/dist/appMap/store.js.map +1 -0
- package/dist/appMap/tsAstScan.js +184 -0
- package/dist/appMap/tsAstScan.js.map +1 -0
- package/dist/artifacts/bundletool.js +199 -0
- package/dist/artifacts/bundletool.js.map +1 -0
- package/dist/artifacts/resolve.js +388 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/automationGen/appiumModel.js +129 -0
- package/dist/automationGen/appiumModel.js.map +1 -0
- package/dist/automationGen/ciEmitter.js +80 -0
- package/dist/automationGen/ciEmitter.js.map +1 -0
- package/dist/automationGen/jsEmitter.js +440 -0
- package/dist/automationGen/jsEmitter.js.map +1 -0
- package/dist/automationGen/packagePatch.js +56 -0
- package/dist/automationGen/packagePatch.js.map +1 -0
- package/dist/automationGen/projectProfile.js +317 -0
- package/dist/automationGen/projectProfile.js.map +1 -0
- package/dist/automationGen/pythonEmitter.js +386 -0
- package/dist/automationGen/pythonEmitter.js.map +1 -0
- package/dist/automationGen/readmeEmitter.js +66 -0
- package/dist/automationGen/readmeEmitter.js.map +1 -0
- package/dist/automationGen/suitePlan.js +94 -0
- package/dist/automationGen/suitePlan.js.map +1 -0
- package/dist/automationGen/validation.js +150 -0
- package/dist/automationGen/validation.js.map +1 -0
- package/dist/build/parseBuildLog.js +119 -0
- package/dist/build/parseBuildLog.js.map +1 -0
- package/dist/build/plan.js +150 -0
- package/dist/build/plan.js.map +1 -0
- package/dist/ci/preflight.js +85 -0
- package/dist/ci/preflight.js.map +1 -0
- package/dist/cli/init.js +105 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan.js +85 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/suite.js +85 -0
- package/dist/cli/suite.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/consent/consent.js +43 -0
- package/dist/consent/consent.js.map +1 -0
- package/dist/context/detect.js +156 -0
- package/dist/context/detect.js.map +1 -0
- package/dist/context/findApps.js +198 -0
- package/dist/context/findApps.js.map +1 -0
- package/dist/context/projectRoot.js +41 -0
- package/dist/context/projectRoot.js.map +1 -0
- package/dist/context/scan.js +167 -0
- package/dist/context/scan.js.map +1 -0
- package/dist/core/target.js +115 -0
- package/dist/core/target.js.map +1 -0
- package/dist/core/targetPlan.js +140 -0
- package/dist/core/targetPlan.js.map +1 -0
- package/dist/drivers/DirectDriver.js +228 -0
- package/dist/drivers/DirectDriver.js.map +1 -0
- package/dist/drivers/Driver.js +4 -0
- package/dist/drivers/Driver.js.map +1 -0
- package/dist/drivers/SimctlDriver.js +127 -0
- package/dist/drivers/SimctlDriver.js.map +1 -0
- package/dist/drivers/WdaDriver.js +250 -0
- package/dist/drivers/WdaDriver.js.map +1 -0
- package/dist/explore/candidates.js +93 -0
- package/dist/explore/candidates.js.map +1 -0
- package/dist/explore/graph.js +116 -0
- package/dist/explore/graph.js.map +1 -0
- package/dist/explore/memory.js +35 -0
- package/dist/explore/memory.js.map +1 -0
- package/dist/explore/planner.js +105 -0
- package/dist/explore/planner.js.map +1 -0
- package/dist/explore/policy.js +85 -0
- package/dist/explore/policy.js.map +1 -0
- package/dist/explore/runner.js +475 -0
- package/dist/explore/runner.js.map +1 -0
- package/dist/explore/signatures.js +35 -0
- package/dist/explore/signatures.js.map +1 -0
- package/dist/explore/suite.js +55 -0
- package/dist/explore/suite.js.map +1 -0
- package/dist/featureTesting/executionBootstrap.js +140 -0
- package/dist/featureTesting/executionBootstrap.js.map +1 -0
- package/dist/firstRun/authStateMachine.js +83 -0
- package/dist/firstRun/authStateMachine.js.map +1 -0
- package/dist/firstRun/classifyScreen.js +201 -0
- package/dist/firstRun/classifyScreen.js.map +1 -0
- package/dist/firstRun/firstRunPlanner.js +207 -0
- package/dist/firstRun/firstRunPlanner.js.map +1 -0
- package/dist/firstRun/firstRunRunner.js +331 -0
- package/dist/firstRun/firstRunRunner.js.map +1 -0
- package/dist/firstRun/generatedDataPolicy.js +215 -0
- package/dist/firstRun/generatedDataPolicy.js.map +1 -0
- package/dist/firstRun/inputPlanner.js +67 -0
- package/dist/firstRun/inputPlanner.js.map +1 -0
- package/dist/firstRun/onboardingStateMachine.js +46 -0
- package/dist/firstRun/onboardingStateMachine.js.map +1 -0
- package/dist/firstRun/paywallPolicy.js +54 -0
- package/dist/firstRun/paywallPolicy.js.map +1 -0
- package/dist/firstRun/types.js +7 -0
- package/dist/firstRun/types.js.map +1 -0
- package/dist/fixtures/catalog.js +131 -0
- package/dist/fixtures/catalog.js.map +1 -0
- package/dist/flows/discover.js +18 -0
- package/dist/flows/discover.js.map +1 -0
- package/dist/flows/generate.js +211 -0
- package/dist/flows/generate.js.map +1 -0
- package/dist/flows/lint.js +97 -0
- package/dist/flows/lint.js.map +1 -0
- package/dist/flows/pack.js +68 -0
- package/dist/flows/pack.js.map +1 -0
- package/dist/flows/run.js +738 -0
- package/dist/flows/run.js.map +1 -0
- package/dist/flows/schema.js +240 -0
- package/dist/flows/schema.js.map +1 -0
- package/dist/flows/seedExec.js +108 -0
- package/dist/flows/seedExec.js.map +1 -0
- package/dist/flows/templates.js +155 -0
- package/dist/flows/templates.js.map +1 -0
- package/dist/flows/waitGuards.js +12 -0
- package/dist/flows/waitGuards.js.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/ios/signing.js +182 -0
- package/dist/ios/signing.js.map +1 -0
- package/dist/issues/classify.js +186 -0
- package/dist/issues/classify.js.map +1 -0
- package/dist/issues/fingerprint.js +130 -0
- package/dist/issues/fingerprint.js.map +1 -0
- package/dist/issues/index.js +240 -0
- package/dist/issues/index.js.map +1 -0
- package/dist/issues/metrics.js +155 -0
- package/dist/issues/metrics.js.map +1 -0
- package/dist/issues/recurrence.js +193 -0
- package/dist/issues/recurrence.js.map +1 -0
- package/dist/issues/report.js +110 -0
- package/dist/issues/report.js.map +1 -0
- package/dist/issues/reportBridge.js +119 -0
- package/dist/issues/reportBridge.js.map +1 -0
- package/dist/issues/schema.js +90 -0
- package/dist/issues/schema.js.map +1 -0
- package/dist/issues/sourceRevision.js +108 -0
- package/dist/issues/sourceRevision.js.map +1 -0
- package/dist/issues/store.js +155 -0
- package/dist/issues/store.js.map +1 -0
- package/dist/lib/android.js +278 -0
- package/dist/lib/android.js.map +1 -0
- package/dist/lib/commandTemplate.js +55 -0
- package/dist/lib/commandTemplate.js.map +1 -0
- package/dist/lib/coordSpace.js +23 -0
- package/dist/lib/coordSpace.js.map +1 -0
- package/dist/lib/device.js +87 -0
- package/dist/lib/device.js.map +1 -0
- package/dist/lib/gitignore.js +22 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/image.js +97 -0
- package/dist/lib/image.js.map +1 -0
- package/dist/lib/logger.js +8 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/metroState.js +45 -0
- package/dist/lib/metroState.js.map +1 -0
- package/dist/lib/needsInput.js +201 -0
- package/dist/lib/needsInput.js.map +1 -0
- package/dist/lib/png.js +103 -0
- package/dist/lib/png.js.map +1 -0
- package/dist/lib/redact.js +21 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/result.js +87 -0
- package/dist/lib/result.js.map +1 -0
- package/dist/lib/schemaHash.js +65 -0
- package/dist/lib/schemaHash.js.map +1 -0
- package/dist/lib/sensitive.js +13 -0
- package/dist/lib/sensitive.js.map +1 -0
- package/dist/lib/simctl.js +149 -0
- package/dist/lib/simctl.js.map +1 -0
- package/dist/lib/spawn.js +144 -0
- package/dist/lib/spawn.js.map +1 -0
- package/dist/lib/wda.js +347 -0
- package/dist/lib/wda.js.map +1 -0
- package/dist/lib/wdaConfig.js +69 -0
- package/dist/lib/wdaConfig.js.map +1 -0
- package/dist/lib/wdaTune.js +58 -0
- package/dist/lib/wdaTune.js.map +1 -0
- package/dist/oracle/auth.js +22 -0
- package/dist/oracle/auth.js.map +1 -0
- package/dist/oracle/failures.js +193 -0
- package/dist/oracle/failures.js.map +1 -0
- package/dist/oracle/health.js +123 -0
- package/dist/oracle/health.js.map +1 -0
- package/dist/oracle/record.js +36 -0
- package/dist/oracle/record.js.map +1 -0
- package/dist/orchestration/envelope.js +52 -0
- package/dist/orchestration/envelope.js.map +1 -0
- package/dist/orchestration/goal.js +98 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/plan/plan.js +124 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/prompts/index.js +63 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/report/artifactManifest.js +44 -0
- package/dist/report/artifactManifest.js.map +1 -0
- package/dist/report/coverage.js +60 -0
- package/dist/report/coverage.js.map +1 -0
- package/dist/report/evidence.js +84 -0
- package/dist/report/evidence.js.map +1 -0
- package/dist/report/export.js +447 -0
- package/dist/report/export.js.map +1 -0
- package/dist/report/flake.js +61 -0
- package/dist/report/flake.js.map +1 -0
- package/dist/report/history.js +564 -0
- package/dist/report/history.js.map +1 -0
- package/dist/report/policy.js +98 -0
- package/dist/report/policy.js.map +1 -0
- package/dist/report/qaLevel.js +96 -0
- package/dist/report/qaLevel.js.map +1 -0
- package/dist/report/readiness.js +213 -0
- package/dist/report/readiness.js.map +1 -0
- package/dist/report/summary.js +42 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/testCatalog.js +93 -0
- package/dist/report/testCatalog.js.map +1 -0
- package/dist/report/timing.js +37 -0
- package/dist/report/timing.js.map +1 -0
- package/dist/server.js +180 -0
- package/dist/server.js.map +1 -0
- package/dist/services/automationGenerate.js +60 -0
- package/dist/services/automationGenerate.js.map +1 -0
- package/dist/services/build.js +66 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/preflight.js +51 -0
- package/dist/services/preflight.js.map +1 -0
- package/dist/services/prepareAndroid.js +183 -0
- package/dist/services/prepareAndroid.js.map +1 -0
- package/dist/services/prepareIos.js +162 -0
- package/dist/services/prepareIos.js.map +1 -0
- package/dist/services/report.js +537 -0
- package/dist/services/report.js.map +1 -0
- package/dist/services/smoke.js +120 -0
- package/dist/services/smoke.js.map +1 -0
- package/dist/services/suiteGenerate.js +123 -0
- package/dist/services/suiteGenerate.js.map +1 -0
- package/dist/services/testSuiteKnowledge.js +150 -0
- package/dist/services/testSuiteKnowledge.js.map +1 -0
- package/dist/session/attach.js +47 -0
- package/dist/session/attach.js.map +1 -0
- package/dist/session/progress.js +56 -0
- package/dist/session/progress.js.map +1 -0
- package/dist/session/store.js +329 -0
- package/dist/session/store.js.map +1 -0
- package/dist/snapshot/overlays.js +132 -0
- package/dist/snapshot/overlays.js.map +1 -0
- package/dist/snapshot/parse.js +204 -0
- package/dist/snapshot/parse.js.map +1 -0
- package/dist/snapshot/present.js +12 -0
- package/dist/snapshot/present.js.map +1 -0
- package/dist/snapshot/settle.js +36 -0
- package/dist/snapshot/settle.js.map +1 -0
- package/dist/state/profile.js +318 -0
- package/dist/state/profile.js.map +1 -0
- package/dist/suite/compile.js +176 -0
- package/dist/suite/compile.js.map +1 -0
- package/dist/suite/lint.js +45 -0
- package/dist/suite/lint.js.map +1 -0
- package/dist/suite/pom.js +285 -0
- package/dist/suite/pom.js.map +1 -0
- package/dist/suite/testcase.js +87 -0
- package/dist/suite/testcase.js.map +1 -0
- package/dist/testSuite/generator.js +222 -0
- package/dist/testSuite/generator.js.map +1 -0
- package/dist/testSuite/history.js +44 -0
- package/dist/testSuite/history.js.map +1 -0
- package/dist/testSuite/issueLinks.js +96 -0
- package/dist/testSuite/issueLinks.js.map +1 -0
- package/dist/testSuite/merge.js +190 -0
- package/dist/testSuite/merge.js.map +1 -0
- package/dist/testSuite/schema.js +86 -0
- package/dist/testSuite/schema.js.map +1 -0
- package/dist/testSuite/store.js +116 -0
- package/dist/testSuite/store.js.map +1 -0
- package/dist/testSuite/traceability.js +55 -0
- package/dist/testSuite/traceability.js.map +1 -0
- package/dist/tools/act.js +457 -0
- package/dist/tools/act.js.map +1 -0
- package/dist/tools/agent.js +225 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/appMap.js +317 -0
- package/dist/tools/appMap.js.map +1 -0
- package/dist/tools/assertVisual.js +74 -0
- package/dist/tools/assertVisual.js.map +1 -0
- package/dist/tools/automationGenerate.js +394 -0
- package/dist/tools/automationGenerate.js.map +1 -0
- package/dist/tools/capabilities.js +114 -0
- package/dist/tools/capabilities.js.map +1 -0
- package/dist/tools/clearOverlay.js +150 -0
- package/dist/tools/clearOverlay.js.map +1 -0
- package/dist/tools/detectContext.js +41 -0
- package/dist/tools/detectContext.js.map +1 -0
- package/dist/tools/doctor.js +116 -0
- package/dist/tools/doctor.js.map +1 -0
- package/dist/tools/explore.js +289 -0
- package/dist/tools/explore.js.map +1 -0
- package/dist/tools/firstRun.js +136 -0
- package/dist/tools/firstRun.js.map +1 -0
- package/dist/tools/flow.js +331 -0
- package/dist/tools/flow.js.map +1 -0
- package/dist/tools/flowGenerate.js +55 -0
- package/dist/tools/flowGenerate.js.map +1 -0
- package/dist/tools/getArtifact.js +39 -0
- package/dist/tools/getArtifact.js.map +1 -0
- package/dist/tools/health.js +41 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/ios.js +492 -0
- package/dist/tools/ios.js.map +1 -0
- package/dist/tools/jobs.js +20 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/network.js +50 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/note.js +69 -0
- package/dist/tools/note.js.map +1 -0
- package/dist/tools/plan.js +49 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/prepareIosTarget.js +99 -0
- package/dist/tools/prepareIosTarget.js.map +1 -0
- package/dist/tools/prepareTarget.js +257 -0
- package/dist/tools/prepareTarget.js.map +1 -0
- package/dist/tools/report.js +42 -0
- package/dist/tools/report.js.map +1 -0
- package/dist/tools/screenRecord.js +24 -0
- package/dist/tools/screenRecord.js.map +1 -0
- package/dist/tools/screenshot.js +63 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/smoke.js +39 -0
- package/dist/tools/smoke.js.map +1 -0
- package/dist/tools/snapshot.js +129 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/startSession.js +169 -0
- package/dist/tools/startSession.js.map +1 -0
- package/dist/tools/state.js +87 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/suite.js +412 -0
- package/dist/tools/suite.js.map +1 -0
- package/dist/tools/testThis.js +774 -0
- package/dist/tools/testThis.js.map +1 -0
- package/dist/tools/wda.js +477 -0
- package/dist/tools/wda.js.map +1 -0
- package/dist/version.js +62 -0
- package/dist/version.js.map +1 -0
- package/dist/visual/ocr.js +72 -0
- package/dist/visual/ocr.js.map +1 -0
- package/dist/visual/provider.js +75 -0
- package/dist/visual/provider.js.map +1 -0
- package/docs/README.md +19 -0
- package/docs/assets/swipium-lockup-ink-on-light.png +0 -0
- package/docs/mcp-server.md +135 -0
- package/docs/tools.md +130 -0
- package/package.json +70 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Parse a uiautomator dump into @eN-referenced elements + a snapshotQuality verdict.
|
|
2
|
+
// (DESIGN §4, §11.) The dump is the Android accessibility tree, so quality is a property
|
|
3
|
+
// of the target app — we measure it rather than pretend a weak tree is strong.
|
|
4
|
+
import { XMLParser } from 'fast-xml-parser';
|
|
5
|
+
import { isSecureNode } from '../lib/redact.js';
|
|
6
|
+
const BOUNDS_RE = /\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/;
|
|
7
|
+
const WEBVIEW_RE = /WebView|SurfaceView|GLSurfaceView|TextureView/i;
|
|
8
|
+
const COMPOSE_RE = /compose/i;
|
|
9
|
+
function bool(v) {
|
|
10
|
+
return v === 'true' || v === true;
|
|
11
|
+
}
|
|
12
|
+
function parseBounds(s) {
|
|
13
|
+
const m = typeof s === 'string' ? s.match(BOUNDS_RE) : null;
|
|
14
|
+
if (!m)
|
|
15
|
+
return [0, 0, 0, 0];
|
|
16
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), Number(m[4])];
|
|
17
|
+
}
|
|
18
|
+
function toRaw(n) {
|
|
19
|
+
const attrs = {};
|
|
20
|
+
for (const [k, v] of Object.entries(n)) {
|
|
21
|
+
if (k === 'node')
|
|
22
|
+
continue;
|
|
23
|
+
attrs[k] = String(v ?? '');
|
|
24
|
+
}
|
|
25
|
+
const kids = n.node;
|
|
26
|
+
return {
|
|
27
|
+
cls: String(n['class'] ?? ''),
|
|
28
|
+
text: String(n['text'] ?? '').trim(),
|
|
29
|
+
desc: String(n['content-desc'] ?? '').trim(),
|
|
30
|
+
id: String(n['resource-id'] ?? '').trim(),
|
|
31
|
+
bounds: parseBounds(String(n['bounds'] ?? '')),
|
|
32
|
+
clickable: bool(n['clickable']),
|
|
33
|
+
longClickable: bool(n['long-clickable']),
|
|
34
|
+
scrollable: bool(n['scrollable']),
|
|
35
|
+
focusable: bool(n['focusable']),
|
|
36
|
+
focused: bool(n['focused']),
|
|
37
|
+
enabled: bool(n['enabled']),
|
|
38
|
+
isLeaf: !Array.isArray(kids) || kids.length === 0,
|
|
39
|
+
attrs,
|
|
40
|
+
dfs: 0, // set during walk
|
|
41
|
+
subtreeEnd: 0,
|
|
42
|
+
drawingOrder: n['drawing-order'] != null ? Number(n['drawing-order']) : -1,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Does a node's bounds contain a point? */
|
|
46
|
+
export function boundsContain(b, x, y) {
|
|
47
|
+
return x >= b[0] && x <= b[2] && y >= b[1] && y <= b[3];
|
|
48
|
+
}
|
|
49
|
+
function role(n) {
|
|
50
|
+
if (/EditText/.test(n.cls))
|
|
51
|
+
return 'text-field';
|
|
52
|
+
if (n.scrollable)
|
|
53
|
+
return 'scrollable';
|
|
54
|
+
if (n.clickable || n.longClickable)
|
|
55
|
+
return 'button';
|
|
56
|
+
if (/ImageView/.test(n.cls))
|
|
57
|
+
return 'image';
|
|
58
|
+
if (n.text || /TextView/.test(n.cls))
|
|
59
|
+
return 'text';
|
|
60
|
+
return n.cls.split('.').pop() || 'node';
|
|
61
|
+
}
|
|
62
|
+
function isSurfaced(n) {
|
|
63
|
+
if (n.clickable || n.longClickable || n.scrollable || /EditText/.test(n.cls))
|
|
64
|
+
return true;
|
|
65
|
+
return n.isLeaf && (n.text.length > 0 || n.desc.length > 0);
|
|
66
|
+
}
|
|
67
|
+
function shortId(id) {
|
|
68
|
+
const i = id.indexOf('/');
|
|
69
|
+
return i >= 0 ? id.slice(i + 1) : id;
|
|
70
|
+
}
|
|
71
|
+
function computeQuality(all, screen) {
|
|
72
|
+
const nodeCount = all.length;
|
|
73
|
+
const clickables = all.filter((n) => n.clickable || n.longClickable);
|
|
74
|
+
const clickableCount = clickables.length;
|
|
75
|
+
const unidentified = clickables.filter((n) => !n.id && !n.desc && !n.text).length;
|
|
76
|
+
const withId = clickables.filter((n) => n.id).length;
|
|
77
|
+
const unidentifiedClickableRatio = clickableCount ? unidentified / clickableCount : 0;
|
|
78
|
+
const idCoverage = clickableCount ? withId / clickableCount : 1;
|
|
79
|
+
const screenArea = Math.max(1, screen[0] * screen[1]);
|
|
80
|
+
let webviewDominance = 0;
|
|
81
|
+
let opaqueWebview = false;
|
|
82
|
+
for (const n of all) {
|
|
83
|
+
if (!WEBVIEW_RE.test(n.cls))
|
|
84
|
+
continue;
|
|
85
|
+
const area = Math.max(0, n.bounds[2] - n.bounds[0]) * Math.max(0, n.bounds[3] - n.bounds[1]);
|
|
86
|
+
const dom = area / screenArea;
|
|
87
|
+
if (dom > webviewDominance) {
|
|
88
|
+
webviewDominance = dom;
|
|
89
|
+
// semantic descendants = surfaced nodes whose bounds sit inside this node
|
|
90
|
+
const kids = all.filter((o) => o !== n &&
|
|
91
|
+
o.bounds[0] >= n.bounds[0] &&
|
|
92
|
+
o.bounds[1] >= n.bounds[1] &&
|
|
93
|
+
o.bounds[2] <= n.bounds[2] &&
|
|
94
|
+
o.bounds[3] <= n.bounds[3] &&
|
|
95
|
+
(o.text || o.desc || o.id)).length;
|
|
96
|
+
opaqueWebview = dom > 0.6 && kids < 3;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const composeNodes = all.filter((n) => COMPOSE_RE.test(n.cls)).length;
|
|
100
|
+
const composeNoTestTag = composeNodes > 0 && idCoverage < 0.1;
|
|
101
|
+
const reasons = [];
|
|
102
|
+
let verdict = 'partial';
|
|
103
|
+
if (nodeCount < 5 ||
|
|
104
|
+
opaqueWebview ||
|
|
105
|
+
unidentifiedClickableRatio > 0.6 ||
|
|
106
|
+
(composeNoTestTag && idCoverage < 0.1)) {
|
|
107
|
+
verdict = 'poor';
|
|
108
|
+
if (nodeCount < 5)
|
|
109
|
+
reasons.push(`only ${nodeCount} nodes (likely splash/canvas/not-rendered)`);
|
|
110
|
+
if (opaqueWebview)
|
|
111
|
+
reasons.push(`a single WebView/SurfaceView covers ${(webviewDominance * 100) | 0}% of screen with no semantic children`);
|
|
112
|
+
if (unidentifiedClickableRatio > 0.6)
|
|
113
|
+
reasons.push(`${(unidentifiedClickableRatio * 100) | 0}% of clickable nodes have no id/label/text`);
|
|
114
|
+
if (composeNoTestTag)
|
|
115
|
+
reasons.push('Compose UI without testTagsAsResourceId (no stable ids)');
|
|
116
|
+
}
|
|
117
|
+
else if (nodeCount >= 15 &&
|
|
118
|
+
unidentifiedClickableRatio < 0.2 &&
|
|
119
|
+
idCoverage > 0.5 &&
|
|
120
|
+
webviewDominance < 0.4) {
|
|
121
|
+
verdict = 'good';
|
|
122
|
+
reasons.push('rich tree with good id coverage');
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
reasons.push(`partial: idCoverage=${idCoverage.toFixed(2)}, unidentifiedClickable=${unidentifiedClickableRatio.toFixed(2)}`);
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
verdict,
|
|
129
|
+
reasons,
|
|
130
|
+
signals: {
|
|
131
|
+
nodeCount,
|
|
132
|
+
clickableCount,
|
|
133
|
+
unidentifiedClickableRatio: Number(unidentifiedClickableRatio.toFixed(3)),
|
|
134
|
+
idCoverage: Number(idCoverage.toFixed(3)),
|
|
135
|
+
webviewDominance: Number(webviewDominance.toFixed(3)),
|
|
136
|
+
composeNoTestTag,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export function parseSnapshot(xml, opts = {}) {
|
|
141
|
+
const interactiveOnly = opts.interactiveOnly ?? true;
|
|
142
|
+
const parser = new XMLParser({
|
|
143
|
+
ignoreAttributes: false,
|
|
144
|
+
attributeNamePrefix: '',
|
|
145
|
+
isArray: (name) => name === 'node',
|
|
146
|
+
});
|
|
147
|
+
const doc = parser.parse(xml);
|
|
148
|
+
const hierarchy = doc?.hierarchy ?? {};
|
|
149
|
+
const roots = Array.isArray(hierarchy.node) ? hierarchy.node : hierarchy.node ? [hierarchy.node] : [];
|
|
150
|
+
const all = [];
|
|
151
|
+
let counter = 0;
|
|
152
|
+
const walk = (n) => {
|
|
153
|
+
const raw = toRaw(n);
|
|
154
|
+
raw.dfs = counter++;
|
|
155
|
+
all.push(raw);
|
|
156
|
+
const kids = n.node;
|
|
157
|
+
if (Array.isArray(kids))
|
|
158
|
+
for (const k of kids)
|
|
159
|
+
walk(k);
|
|
160
|
+
raw.subtreeEnd = counter - 1; // last dfs assigned within this subtree
|
|
161
|
+
};
|
|
162
|
+
for (const r of roots)
|
|
163
|
+
walk(r);
|
|
164
|
+
const screen = all.length ? [all[0].bounds[2], all[0].bounds[3]] : [0, 0];
|
|
165
|
+
const elements = [];
|
|
166
|
+
const fullByRef = new Map();
|
|
167
|
+
let i = 0;
|
|
168
|
+
for (const n of all) {
|
|
169
|
+
if (interactiveOnly && !isSurfaced(n))
|
|
170
|
+
continue;
|
|
171
|
+
if (!interactiveOnly && !isSurfaced(n))
|
|
172
|
+
continue;
|
|
173
|
+
const ref = `@e${++i}`;
|
|
174
|
+
fullByRef.set(ref, n);
|
|
175
|
+
elements.push({
|
|
176
|
+
ref,
|
|
177
|
+
role: role(n),
|
|
178
|
+
label: n.desc || undefined,
|
|
179
|
+
id: n.id ? shortId(n.id) : undefined,
|
|
180
|
+
text: n.text || undefined,
|
|
181
|
+
bounds: n.bounds,
|
|
182
|
+
clickable: n.clickable || n.longClickable,
|
|
183
|
+
focused: n.focused || undefined,
|
|
184
|
+
secure: isSecureNode(n) || undefined,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return { elements, fullByRef, allNodes: all, quality: computeQuality(all, screen), screen, total: all.length };
|
|
188
|
+
}
|
|
189
|
+
/** Stable identity for diffing across snapshots (ignores minor bounds shifts). */
|
|
190
|
+
export function signature(el) {
|
|
191
|
+
return `${el.role}|${el.label ?? ''}|${el.id ?? ''}|${el.text ?? ''}`;
|
|
192
|
+
}
|
|
193
|
+
/** Compact, token-cheap render of the element list for the model. */
|
|
194
|
+
export function renderElements(elements) {
|
|
195
|
+
return elements
|
|
196
|
+
.map((e) => {
|
|
197
|
+
const name = e.label ?? e.text ?? '';
|
|
198
|
+
const id = e.id ? ` #${e.id}` : '';
|
|
199
|
+
const flags = [e.focused ? 'focused' : '', e.clickable ? '' : 'non-clickable'].filter(Boolean).join(',');
|
|
200
|
+
return `${e.ref} [${e.role}] ${JSON.stringify(name)}${id}${flags ? ` (${flags})` : ''}`;
|
|
201
|
+
})
|
|
202
|
+
.join('\n');
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/snapshot/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Present snapshot elements to the model with sensitive-mode applied:
|
|
2
|
+
// - secure fields → value masked to «secure»
|
|
3
|
+
// - any known secret value (typed into a secure field) → scrubbed everywhere
|
|
4
|
+
// Used by qa_snapshot and qa_act so neither leaks credentials.
|
|
5
|
+
import { renderElements } from './parse.js';
|
|
6
|
+
export function presentElements(elements, redact) {
|
|
7
|
+
const masked = elements.map((e) => e.secure
|
|
8
|
+
? { ...e, label: e.label ? '«secure»' : undefined, text: e.text ? '«secure»' : undefined }
|
|
9
|
+
: { ...e, label: redact(e.label), text: redact(e.text) });
|
|
10
|
+
return { elements: masked, rendered: renderElements(masked) };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=present.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"present.js","sourceRoot":"","sources":["../../src/snapshot/present.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,8CAA8C;AAC9C,8EAA8E;AAC9E,+DAA+D;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,UAAU,eAAe,CAC7B,QAA2B,EAC3B,MAAgB;IAEhB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChC,CAAC,CAAC,MAAM;QACN,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE;QAC1F,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAC3D,CAAC;IACF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Settle oracle (DESIGN §5): wait until the accessibility tree stops changing.
|
|
2
|
+
// With OS animations disabled this converges fast. Bounded — never waits forever.
|
|
3
|
+
export async function settle(driver, opts = {}) {
|
|
4
|
+
const timeoutMs = opts.timeoutMs ?? 8000;
|
|
5
|
+
const stableForMs = opts.stableForMs ?? 600;
|
|
6
|
+
const intervalMs = opts.intervalMs ?? 400;
|
|
7
|
+
const deadline = Date.now() + timeoutMs;
|
|
8
|
+
let lastXml = '';
|
|
9
|
+
try {
|
|
10
|
+
lastXml = await driver.dumpXml();
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
/* try again in the loop */
|
|
14
|
+
}
|
|
15
|
+
let stableSince = Date.now();
|
|
16
|
+
while (Date.now() < deadline) {
|
|
17
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
18
|
+
let cur;
|
|
19
|
+
try {
|
|
20
|
+
cur = await driver.dumpXml();
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (cur === lastXml) {
|
|
26
|
+
if (Date.now() - stableSince >= stableForMs)
|
|
27
|
+
return { xml: cur, settled: true };
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
lastXml = cur;
|
|
31
|
+
stableSince = Date.now();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { xml: lastXml, settled: false };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=settle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settle.js","sourceRoot":"","sources":["../../src/snapshot/settle.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kFAAkF;AASlF,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,MAAc,EACd,OAA0E,EAAE;IAE5E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAExC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IACD,IAAI,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;QACpD,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,IAAI,WAAW;gBAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClF,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,GAAG,CAAC;YACd,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, join } from 'node:path';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
import { parseSnapshot } from '../snapshot/parse.js';
|
|
5
|
+
import { executeSeed, seedExactCommand } from '../flows/seedExec.js';
|
|
6
|
+
import { grantPermission, revokePermission } from '../lib/device.js';
|
|
7
|
+
import { privacySet } from '../lib/simctl.js';
|
|
8
|
+
export function loadStateProfile(root, nameOrYaml) {
|
|
9
|
+
const candidates = nameOrYaml.includes('\n') || /name\s*:/.test(nameOrYaml)
|
|
10
|
+
? []
|
|
11
|
+
: [join(root, '.swipium', 'state', `${nameOrYaml}.yaml`), join(root, '.swipium', 'state', `${nameOrYaml}.yml`)];
|
|
12
|
+
const path = candidates.find((p) => existsSync(p));
|
|
13
|
+
const text = path ? readFileSync(path, 'utf8') : nameOrYaml;
|
|
14
|
+
try {
|
|
15
|
+
const profile = parseYaml(text);
|
|
16
|
+
if (!profile?.name)
|
|
17
|
+
return { error: 'state profile needs a name' };
|
|
18
|
+
return { profile, path };
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return { error: `could not parse state profile: ${String(e.message ?? e)}` };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const ANDROID_PERMISSION_ALIASES = {
|
|
25
|
+
notifications: ['android.permission.POST_NOTIFICATIONS'],
|
|
26
|
+
location: ['android.permission.ACCESS_FINE_LOCATION', 'android.permission.ACCESS_COARSE_LOCATION'],
|
|
27
|
+
camera: ['android.permission.CAMERA'],
|
|
28
|
+
microphone: ['android.permission.RECORD_AUDIO'],
|
|
29
|
+
contacts: ['android.permission.READ_CONTACTS'],
|
|
30
|
+
photos: ['android.permission.READ_MEDIA_IMAGES'],
|
|
31
|
+
};
|
|
32
|
+
function permissionsFor(platform, name) {
|
|
33
|
+
if (platform === 'android') {
|
|
34
|
+
if (name.startsWith('android.permission.'))
|
|
35
|
+
return [name];
|
|
36
|
+
return ANDROID_PERMISSION_ALIASES[name] ?? [`android.permission.${name.toUpperCase()}`];
|
|
37
|
+
}
|
|
38
|
+
return [name];
|
|
39
|
+
}
|
|
40
|
+
function resolveAppPath(session, profile) {
|
|
41
|
+
const raw = profile.reset?.appPath ?? profile.appPath;
|
|
42
|
+
if (!raw)
|
|
43
|
+
return undefined;
|
|
44
|
+
return isAbsolute(raw) ? raw : join(session.root, raw);
|
|
45
|
+
}
|
|
46
|
+
function hasLaunchArgs(profile) {
|
|
47
|
+
return !!profile.launch?.arguments && Object.keys(profile.launch.arguments).length > 0;
|
|
48
|
+
}
|
|
49
|
+
function resetPolicyRefusal(profile) {
|
|
50
|
+
const destructiveReset = profile.reset?.android === 'clearData' ||
|
|
51
|
+
profile.reset?.ios === 'reinstallApp' ||
|
|
52
|
+
profile.launch?.clearState === true;
|
|
53
|
+
if (!destructiveReset)
|
|
54
|
+
return null;
|
|
55
|
+
if (profile.reset?.requiresReleaseBuild && !profile.reset.acknowledgeBundleLossRisk)
|
|
56
|
+
return 'release-build reset requires acknowledgeBundleLossRisk:true';
|
|
57
|
+
if (profile.reset?.allowedOnDebugBundle !== true && !profile.reset?.acknowledgeBundleLossRisk)
|
|
58
|
+
return 'debug-bundle reset refused by state profile policy; reset.allowedOnDebugBundle defaults to false';
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function setBlocked(status) {
|
|
62
|
+
return status === 'state_refused' ? status : 'state_blocked';
|
|
63
|
+
}
|
|
64
|
+
function setRefused() {
|
|
65
|
+
return 'state_refused';
|
|
66
|
+
}
|
|
67
|
+
function seedTransaction(input) {
|
|
68
|
+
return {
|
|
69
|
+
fixture: input.fixture,
|
|
70
|
+
phase: input.phase,
|
|
71
|
+
type: input.type,
|
|
72
|
+
exactCommand: input.exactCommand,
|
|
73
|
+
status: input.ok ? 'ok' : 'blocked',
|
|
74
|
+
detail: input.detail,
|
|
75
|
+
warnings: input.warnings?.length ? input.warnings : undefined,
|
|
76
|
+
idempotency: input.idempotent ? 'declared_idempotent' : 'not_declared',
|
|
77
|
+
cleanup: input.cleanup,
|
|
78
|
+
verification: { before: 'not_captured', after: (input.profile.verify?.length ?? 0) > 0 ? 'declared_not_run' : 'not_declared' },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async function assertVisible(driver, query) {
|
|
82
|
+
const q = query.toLowerCase();
|
|
83
|
+
const parsed = parseSnapshot(await driver.dumpXml());
|
|
84
|
+
return parsed.allNodes.some((n) => n.text.toLowerCase().includes(q) || n.desc.toLowerCase().includes(q) || n.id.toLowerCase().includes(q));
|
|
85
|
+
}
|
|
86
|
+
export async function prepareStateProfile(sessions, session, driver, profile) {
|
|
87
|
+
const steps = [];
|
|
88
|
+
const seedTransactions = [];
|
|
89
|
+
const startedAt = new Date().toISOString();
|
|
90
|
+
const appId = profile.appId ?? session.appId;
|
|
91
|
+
let status = 'state_prepared';
|
|
92
|
+
if (profile.reset && profile.reset.android === 'clearData') {
|
|
93
|
+
const policyRefusal = resetPolicyRefusal(profile);
|
|
94
|
+
if (!appId) {
|
|
95
|
+
steps.push({ kind: 'reset.android.clearData', status: 'blocked', detail: 'no appId available' });
|
|
96
|
+
status = 'state_blocked';
|
|
97
|
+
}
|
|
98
|
+
else if (policyRefusal) {
|
|
99
|
+
steps.push({ kind: 'reset.android.clearData', status: 'refused', detail: policyRefusal });
|
|
100
|
+
status = setRefused();
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
await driver.clearData(appId);
|
|
104
|
+
sessions.addEnvChange(session, `state reset clearData ${appId}`);
|
|
105
|
+
steps.push({ kind: 'reset.android.clearData', status: 'ok', detail: appId });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (profile.reset && profile.reset.ios === 'reinstallApp') {
|
|
109
|
+
const appPath = resolveAppPath(session, profile);
|
|
110
|
+
const policyRefusal = resetPolicyRefusal(profile);
|
|
111
|
+
if (!appId) {
|
|
112
|
+
steps.push({ kind: 'reset.ios.reinstallApp', status: 'blocked', detail: 'no appId available' });
|
|
113
|
+
status = setBlocked(status);
|
|
114
|
+
}
|
|
115
|
+
else if (!appPath) {
|
|
116
|
+
steps.push({ kind: 'reset.ios.reinstallApp', status: 'blocked', detail: 'profile.reset.appPath or profile.appPath is required' });
|
|
117
|
+
status = setBlocked(status);
|
|
118
|
+
}
|
|
119
|
+
else if (policyRefusal) {
|
|
120
|
+
steps.push({ kind: 'reset.ios.reinstallApp', status: 'refused', detail: policyRefusal });
|
|
121
|
+
status = setRefused();
|
|
122
|
+
}
|
|
123
|
+
else if (!driver.uninstallApp) {
|
|
124
|
+
steps.push({ kind: 'reset.ios.reinstallApp', status: 'blocked', detail: `${driver.kind} backend cannot uninstall apps` });
|
|
125
|
+
status = setBlocked(status);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
await driver.terminateApp(appId).catch(() => { });
|
|
129
|
+
await driver.uninstallApp(appId).catch(() => { });
|
|
130
|
+
await driver.installApp(appPath);
|
|
131
|
+
sessions.addEnvChange(session, `state reset reinstallApp ${appId} from ${appPath}`);
|
|
132
|
+
steps.push({ kind: 'reset.ios.reinstallApp', status: 'ok', detail: `${appId} from ${appPath}` });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (status !== 'state_refused' && status !== 'state_blocked' && profile.launch?.clearState) {
|
|
136
|
+
const policyRefusal = resetPolicyRefusal(profile);
|
|
137
|
+
if (!appId) {
|
|
138
|
+
steps.push({ kind: 'launch.clearState', status: 'blocked', detail: 'no appId available' });
|
|
139
|
+
status = setBlocked(status);
|
|
140
|
+
}
|
|
141
|
+
else if (policyRefusal) {
|
|
142
|
+
steps.push({ kind: 'launch.clearState', status: 'refused', detail: policyRefusal });
|
|
143
|
+
status = setRefused();
|
|
144
|
+
}
|
|
145
|
+
else if (driver.kind === 'direct') {
|
|
146
|
+
await driver.clearData(appId);
|
|
147
|
+
sessions.addEnvChange(session, `state launch.clearState ${appId}`);
|
|
148
|
+
steps.push({ kind: 'launch.clearState', status: 'ok', detail: appId });
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const appPath = resolveAppPath(session, profile);
|
|
152
|
+
if (appPath && driver.uninstallApp) {
|
|
153
|
+
await driver.terminateApp(appId).catch(() => { });
|
|
154
|
+
await driver.uninstallApp(appId).catch(() => { });
|
|
155
|
+
await driver.installApp(appPath);
|
|
156
|
+
sessions.addEnvChange(session, `state launch.clearState reinstall ${appId}`);
|
|
157
|
+
steps.push({ kind: 'launch.clearState', status: 'ok', detail: `reinstalled ${appId}` });
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
steps.push({ kind: 'launch.clearState', status: 'blocked', detail: 'non-Android clearState requires appPath and uninstall support' });
|
|
161
|
+
status = setBlocked(status);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (status !== 'state_refused' && status !== 'state_blocked' && profile.launch?.permissions && Object.keys(profile.launch.permissions).length) {
|
|
166
|
+
if (!appId) {
|
|
167
|
+
steps.push({ kind: 'permissions', status: 'blocked', detail: 'no appId available' });
|
|
168
|
+
status = setBlocked(status);
|
|
169
|
+
}
|
|
170
|
+
else if (driver.kind === 'direct') {
|
|
171
|
+
const serial = driver.currentDevice();
|
|
172
|
+
if (!serial) {
|
|
173
|
+
steps.push({ kind: 'permissions.android', status: 'blocked', detail: 'no adb serial available' });
|
|
174
|
+
status = setBlocked(status);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
for (const [name, desired] of Object.entries(profile.launch.permissions)) {
|
|
178
|
+
for (const permission of permissionsFor('android', name)) {
|
|
179
|
+
if (desired === 'allow') {
|
|
180
|
+
await grantPermission(serial, appId, permission);
|
|
181
|
+
sessions.addEnvChange(session, `state permission grant ${permission} to ${appId}`);
|
|
182
|
+
steps.push({ kind: `permissions.android.${permission}`, status: 'ok', detail: 'grant' });
|
|
183
|
+
}
|
|
184
|
+
else if (desired === 'deny') {
|
|
185
|
+
await revokePermission(serial, appId, permission);
|
|
186
|
+
sessions.addEnvChange(session, `state permission revoke ${permission} from ${appId}`);
|
|
187
|
+
steps.push({ kind: `permissions.android.${permission}`, status: 'ok', detail: 'revoke' });
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
steps.push({ kind: `permissions.android.${permission}`, status: 'blocked', detail: 'unset is not supported per-permission on Android' });
|
|
191
|
+
status = setBlocked(status);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else if ((driver.kind === 'simulator' || driver.kind === 'wda') && driver.currentDevice()) {
|
|
198
|
+
const udid = driver.currentDevice();
|
|
199
|
+
for (const [name, desired] of Object.entries(profile.launch.permissions)) {
|
|
200
|
+
for (const service of permissionsFor('ios', name)) {
|
|
201
|
+
const action = desired === 'allow' ? 'grant' : desired === 'deny' ? 'revoke' : 'reset';
|
|
202
|
+
await privacySet(udid, action, service, appId);
|
|
203
|
+
sessions.addEnvChange(session, `state ios privacy ${action} ${service}${appId ? ` ${appId}` : ''}`);
|
|
204
|
+
steps.push({ kind: `permissions.ios.${service}`, status: 'ok', detail: action });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
steps.push({ kind: 'permissions', status: 'blocked', detail: `${driver.kind} backend cannot apply state-profile permissions` });
|
|
210
|
+
status = setBlocked(status);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (status !== 'state_refused' && status !== 'state_blocked' && profile.launch) {
|
|
214
|
+
if (!appId) {
|
|
215
|
+
steps.push({ kind: 'launch', status: 'blocked', detail: 'no appId available' });
|
|
216
|
+
status = 'state_blocked';
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
if (profile.launch.stopApp)
|
|
220
|
+
await driver.terminateApp(appId).catch(() => { });
|
|
221
|
+
if (hasLaunchArgs(profile)) {
|
|
222
|
+
if (!driver.launchAppWithArgs) {
|
|
223
|
+
steps.push({ kind: 'launch.arguments', status: 'blocked', detail: `${driver.kind} backend cannot launch with arguments` });
|
|
224
|
+
status = 'state_blocked';
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
await driver.launchAppWithArgs(appId, profile.launch.arguments ?? {});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
await driver.launchApp(appId);
|
|
232
|
+
}
|
|
233
|
+
if (status !== 'state_blocked') {
|
|
234
|
+
sessions.addEnvChange(session, `state launch ${appId}`);
|
|
235
|
+
steps.push({ kind: 'launch', status: 'ok', detail: JSON.stringify({ arguments: profile.launch.arguments ?? null, permissions: profile.launch.permissions ?? null }) });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (status !== 'state_refused' && status !== 'state_blocked') {
|
|
240
|
+
for (const seed of profile.seed ?? []) {
|
|
241
|
+
const fixture = session.fixtures.find((f) => f.name === seed.fixture);
|
|
242
|
+
if (!fixture?.seed) {
|
|
243
|
+
steps.push({ kind: `seed.${seed.fixture}`, status: 'blocked', detail: 'fixture has no seed spec' });
|
|
244
|
+
status = 'state_blocked';
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
const r = await executeSeed(sessions, session, driver, seed.fixture, fixture.seed);
|
|
248
|
+
steps.push({ kind: `seed.${seed.fixture}`, status: r.ok ? 'ok' : 'blocked', detail: r.detail ?? r.warnings.join(' ') });
|
|
249
|
+
seedTransactions.push(seedTransaction({
|
|
250
|
+
fixture: seed.fixture,
|
|
251
|
+
phase: 'prepare',
|
|
252
|
+
type: fixture.seed.type,
|
|
253
|
+
exactCommand: seedExactCommand(fixture.seed),
|
|
254
|
+
ok: r.ok,
|
|
255
|
+
detail: r.detail,
|
|
256
|
+
warnings: r.warnings,
|
|
257
|
+
idempotent: fixture.seed.idempotent,
|
|
258
|
+
cleanup: fixture.seed.cleanup ? 'declared' : 'not_declared',
|
|
259
|
+
profile,
|
|
260
|
+
}));
|
|
261
|
+
if (!r.ok)
|
|
262
|
+
status = 'state_blocked';
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return { profile: profile.name, status, steps, seedTransactions: seedTransactions.length ? seedTransactions : undefined, startedAt, endedAt: new Date().toISOString() };
|
|
266
|
+
}
|
|
267
|
+
export async function verifyStateProfile(driver, profile) {
|
|
268
|
+
const steps = [];
|
|
269
|
+
const startedAt = new Date().toISOString();
|
|
270
|
+
let status = 'state_verified';
|
|
271
|
+
for (const v of profile.verify ?? []) {
|
|
272
|
+
if (!v.assertVisible)
|
|
273
|
+
continue;
|
|
274
|
+
const ok = await assertVisible(driver, v.assertVisible);
|
|
275
|
+
steps.push({ kind: `verify.assertVisible.${v.assertVisible}`, status: ok ? 'ok' : 'blocked' });
|
|
276
|
+
if (!ok)
|
|
277
|
+
status = 'state_blocked';
|
|
278
|
+
}
|
|
279
|
+
return { profile: profile.name, status, steps, startedAt, endedAt: new Date().toISOString() };
|
|
280
|
+
}
|
|
281
|
+
export async function teardownStateProfile(sessions, session, driver, profile) {
|
|
282
|
+
const steps = [];
|
|
283
|
+
const seedTransactions = [];
|
|
284
|
+
const startedAt = new Date().toISOString();
|
|
285
|
+
let status = 'state_torn_down';
|
|
286
|
+
for (const seed of [...(profile.seed ?? [])].reverse()) {
|
|
287
|
+
const fixture = session.fixtures.find((f) => f.name === seed.fixture);
|
|
288
|
+
const cleanup = fixture?.seed?.cleanup;
|
|
289
|
+
if (!fixture?.seed || !cleanup)
|
|
290
|
+
continue;
|
|
291
|
+
const r = await executeSeed(sessions, session, driver, `${seed.fixture}-cleanup`, cleanup);
|
|
292
|
+
steps.push({ kind: `seedCleanup.${seed.fixture}`, status: r.ok ? 'ok' : 'blocked', detail: r.detail ?? r.warnings.join(' ') });
|
|
293
|
+
seedTransactions.push(seedTransaction({
|
|
294
|
+
fixture: seed.fixture,
|
|
295
|
+
phase: 'cleanup',
|
|
296
|
+
type: cleanup.type,
|
|
297
|
+
exactCommand: seedExactCommand(cleanup),
|
|
298
|
+
ok: r.ok,
|
|
299
|
+
detail: r.detail,
|
|
300
|
+
warnings: r.warnings,
|
|
301
|
+
idempotent: fixture.seed.idempotent,
|
|
302
|
+
cleanup: r.ok ? 'executed' : 'blocked',
|
|
303
|
+
profile,
|
|
304
|
+
}));
|
|
305
|
+
if (!r.ok)
|
|
306
|
+
status = 'state_blocked';
|
|
307
|
+
}
|
|
308
|
+
for (const t of profile.teardown ?? []) {
|
|
309
|
+
const networkOnline = t === 'networkOnline' || (typeof t === 'object' && t.networkOnline);
|
|
310
|
+
if (networkOnline) {
|
|
311
|
+
await driver.setAirplane(false);
|
|
312
|
+
sessions.addEnvChange(session, `state teardown networkOnline ${profile.name}`);
|
|
313
|
+
steps.push({ kind: 'teardown.networkOnline', status: 'ok' });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return { profile: profile.name, status, steps, seedTransactions: seedTransactions.length ? seedTransactions : undefined, startedAt, endedAt: new Date().toISOString() };
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/state/profile.ts"],"names":[],"mappings":"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"}
|