mirror of
https://github.com/CharlesWiltgen/Axiom.git
synced 2026-09-20 19:58:20 +08:00
e996de9d79
AXe's default tap style sends a simulator tap that SwiftUI controls ignore while AXe still prints a success line. Measured on Xcode 27.1 with AXe 1.8.0, across iPhone 17 (iOS 27.0) and iPhone Duo (iOS 27.1): neither a Button, a List row, a Button inside a List, a Menu, a row of an open Menu nor a TabView tab activated under the default or the `simulator` style, and `--tap-style physical` activated all six. The same default left system alerts on screen while `dialog accept` reported them handled. `tap` and the `dialog` accept/dismiss taps now supply the physical style unless the caller picks one, and an AXe older than 1.7.0 — which has no `--tap-style` — is named as the cause instead of surfacing as an unknown-flag failure. With more than one simulator booted and no `--udid`, every device verb now exits 2 and lists each booted device's UDID, name and runtime, rather than driving whichever sorted first while reporting success. `doctor` reports that list, fails its gate in that state, and leaves `booted_udid` empty, because nothing may be targeted until the caller chooses.
76 lines
3.0 KiB
Go
76 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
const version = "0.1.0-dev"
|
|
|
|
const usage = `xcui — scriptable iOS-simulator UI & accessibility testing for LLMs
|
|
|
|
Usage:
|
|
xcui doctor [--install] Verify AXe/brew/Xcode/booted-sim; --install adds AXe via brew
|
|
xcui wait --for-element <id> | --gone <id> | --idle Poll the a11y tree until a condition holds
|
|
xcui assert --id <id> [--label <s>] [--value <s>] [--trait <role>] [--single] Assert on an element
|
|
xcui a11y set --toggle <name> --value <on|off> [--app <bundle-id>] Set an accessibility setting
|
|
xcui a11y reset Clear xcui-set accessibility overrides
|
|
xcui dialog accept | dismiss Tap the right button on the frontmost system alert
|
|
xcui dialog pregrant <bundle-id> <service>... Grant permissions so no dialog appears
|
|
xcui voiceover traverse Emit the computed VoiceOver announcement sequence
|
|
xcui voiceover assert --sequence <file> Compare the announcement sequence to an expected one
|
|
xcui resize sweep --sizes <WxH,...> [--screenshot-dir <d>] [--assert-id <id>] [--strict]
|
|
Drive breakpoints, shoot and assert each (OS 27+)
|
|
|
|
Input (forwarded to AXe — same flags, output and exit code; tap also gets
|
|
--tap-style physical unless you pass a style):
|
|
xcui tap | slider | type | swipe | drag | touch | gesture Drive the UI
|
|
xcui button | key | key-sequence | key-combo Hardware buttons and keys
|
|
xcui screenshot Capture the display as PNG
|
|
|
|
Prefer these over calling 'axe' directly: they inherit xcui's SimulatorKit/
|
|
DEVELOPER_DIR handling, so they keep working under an Xcode that AXe cannot load
|
|
on its own. Run 'xcui tap --help' to see AXe's own flags for a verb.
|
|
|
|
Default output is JSON; pass --human for prose. Verbs auto-resolve the booted
|
|
simulator when exactly one is booted; with several, they exit 2 and list them —
|
|
pass --udid to name the one you mean.
|
|
|
|
Run 'xcui <command> --help' for per-command flags.
|
|
`
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
fmt.Fprint(os.Stderr, usage)
|
|
os.Exit(2)
|
|
}
|
|
switch os.Args[1] {
|
|
case "doctor":
|
|
os.Exit(runDoctor(os.Stdout, os.Args[2:]))
|
|
case "wait":
|
|
os.Exit(runWait(os.Stdout, os.Args[2:]))
|
|
case "assert":
|
|
os.Exit(runAssert(os.Stdout, os.Args[2:]))
|
|
case "a11y":
|
|
os.Exit(runA11y(os.Stdout, os.Args[2:]))
|
|
case "dialog":
|
|
os.Exit(runDialog(os.Stdout, os.Args[2:]))
|
|
case "voiceover":
|
|
os.Exit(runVoiceOver(os.Stdout, os.Args[2:]))
|
|
case "resize":
|
|
os.Exit(runResize(os.Stdout, os.Args[2:]))
|
|
case "--version", "-v":
|
|
fmt.Println(version)
|
|
case "--help", "-h":
|
|
fmt.Print(usage)
|
|
default:
|
|
// Input verbs forward to AXe. Checked after the named commands so xcui's own
|
|
// verbs always win a name collision with a future AXe subcommand.
|
|
if _, ok := axeInputVerbs[os.Args[1]]; ok {
|
|
os.Exit(runInput(os.Stdout, os.Args[1], os.Args[2:]))
|
|
}
|
|
fmt.Fprintf(os.Stderr, "unknown command: %s\n\n%s", os.Args[1], usage)
|
|
os.Exit(2)
|
|
}
|
|
}
|