mirror of
https://github.com/software-mansion/argent.git
synced 2026-09-14 19:27:14 +08:00
cd4190b80e
Now verified end-to-end on the real Mac: install/introspection/validation, the android tier (against a booted emulator), and the chromium tier all pass from a locally packed tgz; the rn tier auto-skips without `~/dev/bluesky` as designed. ## What this is A release-gating end-to-end harness under `scripts/e2e-full/` that starts from **only a `swmansion-argent-*.tgz` bundle** and exercises the whole product: the install flow, every CLI command, all 70 tools' argument validation, and a happy-path run of every tool against real devices. Intended to be run on the real Linux box and the real Mac before a release. Everything runs under a throwaway `HOME` + npm prefix, so it never touches the machine's real `~/.argent`, editor MCP configs, or global packages (safe on a shared box). It emits a JSONL log + a markdown coverage report and exits non-zero if any hard assertion fails. ## Phases | phase | needs | covers | |---|---|---| | `install` | npm + network | `npm i -g <tgz>`, bundled binaries, `init` (global + `--local`), `update`, `uninstall`, telemetry, MCP-config generation | | `introspection` | — | `--version/--help`, `tools describe` for **all 70** tools, feature flags, `server start/status/logs/stop`, `link/unlink` | | `validation` | — | per tool: missing-required / bad-enum / bad-type rejection (schema-driven, no hardware) | | `android` | Android emulator | happy-path of every touch/gesture/screenshot/app-lifecycle tool | | `chromium` | Electron (bundled optional dep) + a display | boots a generated Electron app; drives CDP tools (scroll/drag/tabs/cookies/storage) | | `rn` | `~/dev/bluesky` + Android device | debugger + react/native profiler + network chain against the real Bluesky app | Tiers auto-skip with a recorded reason when prerequisites are missing. iOS / tvOS / Vega are intentionally out of scope for now. ## What I actually verified (real runs, Linux) - **install** 18✓/0✗, **introspection** 85✓/0✗ (all 70 `tools describe`), **validation** 81✓/0✗, **chromium** 24✓/0✗ (real Electron app + CDP). - Holistic run: **190✓ / 0✗ / 34∼, exit 0.** Failure-gate confirmed (non-zero on fail), `bash -n` clean on all files, all 72 android/rn JSON arg literals linted. ## What I did NOT verify live (please scrutinize) - **`android` and `rn` tiers were never run against a live device.** The Android emulator would not stay up on my box (memory-constrained shared machine; QEMU threads hung seconds after boot across ~7 attempts). The code is complete and uses the same machinery the `chromium` tier exercised live, but it has **not** been proven end-to-end. This is the main reason for the "not certain how well it works" caveat. - The RN tier's exact debugger/profiler arg shapes are derived from `tools describe`, not confirmed against a running Metro. ## Run it ```bash bash scripts/e2e-full/run-e2e.sh # everything applicable to this OS bash scripts/e2e-full/run-e2e.sh --skip-install --phase introspection,validation # fast offline core bash scripts/e2e-full/run-e2e.sh --phase android --android-serial emulator-5554 # inject a device ```
100 lines
3.8 KiB
Bash
100 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Phase 2 — Argument-matrix validation (offline, no device).
|
|
#
|
|
# For EVERY tool, generates rejection cases straight from its parsed schema:
|
|
# - missing-required : omit all required flags -> must reject
|
|
# - bad-enum : junk value for each enum flag -> must reject (that path)
|
|
# - bad-type : string where a number is required -> must reject (that path)
|
|
#
|
|
# Valid-typed dummies are filled for the *other* required flags so the single
|
|
# intended violation is what trips the rejection. This is deterministic and
|
|
# needs no hardware — it's the "every combination of arguments" guarantee at the
|
|
# validation layer. Runs against the private tool-server started in phase 1.
|
|
|
|
# Tools with no required flags that would actually EXECUTE (touch a device /
|
|
# network / state) if called empty — excluded from missing-required here and
|
|
# covered by the device tiers instead.
|
|
_VAL_EXCLUDE_MISSING="list-devices stop-all-simulator-servers stop-metro native-devtools-status update-argent"
|
|
|
|
# Build a JSON object with valid dummies for every required flag in a model,
|
|
# then apply overrides "field=raw-json" pairs. Emits the JSON on stdout.
|
|
_build_args() { # model [field:rawjson ...]
|
|
local model="$1"; shift
|
|
python3 - "$model" "$@" <<'PY'
|
|
import json, sys
|
|
model = sys.argv[1]
|
|
overrides = {}
|
|
for a in sys.argv[2:]:
|
|
k, v = a.split("=", 1)
|
|
overrides[k] = json.loads(v)
|
|
obj = {}
|
|
with open(model) as fh:
|
|
for line in fh:
|
|
line = line.rstrip("\n")
|
|
if not line:
|
|
continue
|
|
name, kind, req, enums = (line.split("\t") + ["", "", "", ""])[:4]
|
|
if req != "1":
|
|
continue
|
|
if kind == "number":
|
|
obj[name] = 1
|
|
elif kind == "boolean":
|
|
obj[name] = True
|
|
elif kind == "enum":
|
|
obj[name] = (enums.split(",")[0] if enums else "x")
|
|
elif kind == "array":
|
|
obj[name] = []
|
|
elif kind == "object":
|
|
obj[name] = {}
|
|
else:
|
|
obj[name] = "x"
|
|
obj.update(overrides)
|
|
print(json.dumps(obj))
|
|
PY
|
|
}
|
|
|
|
run_phase() {
|
|
local P=validation
|
|
ensure_server || warn "no private server; validation still runs (client-side schema)"
|
|
|
|
local names t model
|
|
names="$(list_tool_names)"
|
|
|
|
while read -r t; do
|
|
[ -z "$t" ] && continue
|
|
model="$(parse_tool_model "$t")"
|
|
[ -s "$model" ] || { skip "$P" "$t" schema "no flags to validate"; continue; }
|
|
|
|
local reqs; reqs="$(model_required_flags "$model")"
|
|
|
|
# --- missing-required ---------------------------------------------------
|
|
if [ -n "$reqs" ]; then
|
|
local first_req; first_req="$(printf '%s\n' "$reqs" | head -1)"
|
|
# omit everything -> the first required flag must be flagged undefined
|
|
assert_reject "$P" "$t" missing-required '{}' "$first_req" "invalid_type"
|
|
else
|
|
case " $_VAL_EXCLUDE_MISSING " in
|
|
*" $t "*) : ;; # device/stateful no-arg tool: covered elsewhere
|
|
*) skip "$P" "$t" missing-required "no required flags" ;;
|
|
esac
|
|
fi
|
|
|
|
# --- bad-enum (one case per enum flag) ---------------------------------
|
|
local ef
|
|
for ef in $(model_enum_flags "$model"); do
|
|
local args; args="$(_build_args "$model" "$ef=\"__not_a_valid_enum__\"")"
|
|
assert_reject "$P" "$t" "bad-enum:$ef" "$args" "$ef" "invalid_value"
|
|
done
|
|
|
|
# --- bad-type (first required number flag gets a string) ---------------
|
|
local nf
|
|
nf="$(model_number_flags "$model" | while read -r f; do
|
|
awk -F'\t' -v n="$f" '$1==n && $3==1{print n}' "$model"; done | head -1)"
|
|
if [ -z "$nf" ]; then nf="$(model_number_flags "$model" | head -1)"; fi
|
|
if [ -n "$nf" ]; then
|
|
local targs; targs="$(_build_args "$model" "$nf=\"not_a_number\"")"
|
|
assert_reject "$P" "$t" "bad-type:$nf" "$targs" "$nf" "invalid_type"
|
|
fi
|
|
done <<< "$names"
|
|
}
|