@goliapkg/smix
v9.0.0
Published
Playwright-shape iOS Simulator / Android emulator UI automation SDK for React Native + Expo + Detox-compatible TypeScript test runners.
Readme
@goliapkg/smix
TypeScript types and host-side building blocks for smix — AI-native UI automation for the iOS Simulator and Android emulator.
Live driving runs through the napi addon. This package ships the same
typed API surface as the Swift / Kotlin / Rust SDKs; Smix.launchApp,
App.tap, App.fill, and the rest drive a device by calling into
@goliapkg/smix-node. Smix.launchApp loads the per-platform addon
automatically (via loadNodeDriver); the addon is built by a per-triple
prebuild matrix in CI, and its npm release follows in a later version — you
can also inject a NodeDriver explicitly for tests or a custom transport.
Three surfaces still throw SmixNotImplementedError pending their transport:
App.screenshot and App.openUrl need a runner wire route, and
App.launchFresh needs host-side state clearing. To drive a device without
the addon today, use the smix CLI or
one of the Swift / Kotlin / Rust SDKs.
What works today
- Selector DSL — the full selector language, encoding to the exact JSON wire shape the Rust core resolves.
- Session lifecycle —
Session.open/stillValid/relaunchApp/renewActivation/closeagainst a running smix runner, over HTTP. ExpectationFailure— parse and produce smix's AI-readable failure JSON.A11yNode— typed accessibility-tree model withflatten/findById/rectCenterhelpers for working withsmix tree --jsonoutput.
Installation
bun add -D @goliapkg/smix
# OR
npm install -D @goliapkg/smixTest-target only: keep it in devDependencies, never bundled into a
production RN / Expo app.
Selector
import { Selector, literal, regex } from '@goliapkg/smix'
Selector.id('btn-login')
Selector.text(literal('Sign In'))
Selector.text(regex('^Sub', 'i'))
Selector.label('Settings')
Selector.role('button', literal('Submit'))
Selector.localizedText({ en: 'Submit', ja: '送信' })
// Fluent modifier chaining (returns a new Selector)
Selector.id('btn').below(Selector.text(literal('Address'))).nth(0)
Selector.role('button').near(Selector.text(literal('Confirm')))Wire JSON (untagged + flattened — byte-identical to Rust smix-selector):
{"id": "btn-login", "below": {"text": "Address"}, "nth": 0}Session lifecycle
import { HttpSimRuntime, Session } from '@goliapkg/smix'
const runtime = new HttpSimRuntime('http://127.0.0.1:22087')
const session = await Session.open(runtime, 'com.example.app')
await session.relaunchApp()
await session.close()HttpSimRuntime also exposes resolver / labelsResolver, which
resolve a selector against a caller-supplied tree JSON via the runner's
/select/resolve routes.
ExpectationFailure
import { ExpectationFailure } from '@goliapkg/smix'
try {
// a driving call, once the native transport lands
} catch (e) {
if (e instanceof ExpectationFailure) {
e.code // 'ELEMENT_NOT_FOUND' | 'AMBIGUOUS' | 'TIMEOUT' | ...
e.visibleElements // A11yNode[] — context for AI diagnosis
e.suggestions // string[]
e.toJson() // single-line JSON for agent consumption
}
}License
Apache-2.0 OR MIT (dual, at your option).
