diff --git a/pkg/spec-api/src/actions.ts b/pkg/spec-api/src/actions.ts new file mode 100644 index 0000000..2d0a758 --- /dev/null +++ b/pkg/spec-api/src/actions.ts @@ -0,0 +1,36 @@ +import type { + AccessibilityElement, + Action, + ActionGenerator, + InputTextAction, + TapAction, + WeightedEntry, +} from "./types.ts"; + +export function actions(generator: () => Action[]): ActionGenerator { + return globalThis.__uatu__.actions(generator); +} + +export function weighted(...entries: WeightedEntry[]): ActionGenerator { + return globalThis.__uatu__.weighted(...entries); +} + +export function Tap(parameters: { on: string | AccessibilityElement }): TapAction { + return globalThis.__uatu__.tap(parameters); +} + +export function InputText(parameters: { into: string | AccessibilityElement; text: string }): InputTextAction { + return globalThis.__uatu__.inputText(parameters); +} + +export const taps: ActionGenerator = new Proxy({} as ActionGenerator, { + get(_target, property) { + return (globalThis.__uatu__.taps as unknown as Record)[property]; + }, +}); + +export const swipes: ActionGenerator = new Proxy({} as ActionGenerator, { + get(_target, property) { + return (globalThis.__uatu__.swipes as unknown as Record)[property]; + }, +}); diff --git a/pkg/spec-api/src/extract.ts b/pkg/spec-api/src/extract.ts new file mode 100644 index 0000000..a0181d7 --- /dev/null +++ b/pkg/spec-api/src/extract.ts @@ -0,0 +1,5 @@ +import type { Extracted, State } from "./types.ts"; + +export function extract(getter: (state: State) => T): Extracted { + return globalThis.__uatu__.extract(getter); +} diff --git a/pkg/spec-api/src/index.ts b/pkg/spec-api/src/index.ts new file mode 100644 index 0000000..b74ca53 --- /dev/null +++ b/pkg/spec-api/src/index.ts @@ -0,0 +1,17 @@ +export type { + AccessibilityElement, + AccessibilityTree, + Action, + ActionGenerator, + Extracted, + Formula, + InputTextAction, + Snapshots, + State, + TapAction, + WeightedEntry, +} from "./types.ts"; + +export { extract } from "./extract.ts"; +export { always } from "./ltl.ts"; +export { Tap, InputText, actions, weighted, taps, swipes } from "./actions.ts"; diff --git a/pkg/spec-api/src/ltl.ts b/pkg/spec-api/src/ltl.ts new file mode 100644 index 0000000..381e3af --- /dev/null +++ b/pkg/spec-api/src/ltl.ts @@ -0,0 +1,5 @@ +import type { Formula } from "./types.ts"; + +export function always(predicate: () => boolean): Formula { + return globalThis.__uatu__.always(predicate); +} diff --git a/pkg/spec-api/src/types.ts b/pkg/spec-api/src/types.ts new file mode 100644 index 0000000..1b02c16 --- /dev/null +++ b/pkg/spec-api/src/types.ts @@ -0,0 +1,53 @@ +export type Snapshots = Record; + +export interface AccessibilityElement { + id?: string; + text?: string; + bounds?: { left: number; top: number; right: number; bottom: number }; +} + +export interface AccessibilityTree { + find(selector: string): AccessibilityElement | undefined; + findAll(selector: string): AccessibilityElement[]; +} + +export interface State { + snapshots: Snapshots; + ax: AccessibilityTree; +} + +export interface Extracted { + readonly current: T; + readonly previous: T | undefined; +} + +export type TapAction = { kind: "Tap"; on: string | AccessibilityElement }; +export type InputTextAction = { kind: "InputText"; into: string | AccessibilityElement; text: string }; +export type Action = TapAction | InputTextAction; + +export interface ActionGenerator { + readonly __uatuActionGenerator: true; + generate(): Action[]; +} + +export interface Formula { + readonly __uatuFormula: true; +} + +export interface UatuRuntime { + extract: (getter: (state: State) => T) => Extracted; + always: (predicate: () => boolean) => Formula; + actions: (generator: () => Action[]) => ActionGenerator; + weighted: (...entries: WeightedEntry[]) => ActionGenerator; + tap: (parameters: { on: string | AccessibilityElement }) => TapAction; + inputText: (parameters: { into: string | AccessibilityElement; text: string }) => InputTextAction; + taps: ActionGenerator; + swipes: ActionGenerator; +} + +export type WeightedEntry = readonly [number, ActionGenerator]; + +declare global { + // eslint-disable-next-line no-var + var __uatu__: UatuRuntime; +}