From 8309fb1886bc824b958d065697f13248c637cc49 Mon Sep 17 00:00:00 2001 From: PJ Date: Mon, 27 Apr 2026 00:54:55 +0700 Subject: [PATCH] feat(spec): type AttrSelector with known attribute names Replace AttrSelector = Record with KnownAttrSelectors plus a string|boolean index signature, so authors get autocomplete and type-checking on testTag / focused / clickable / etc. while raw driver attributes still type-check via the fallback. Boolean state attributes accept native booleans; goja stringifies them at the marshal boundary. AccessibilityElement.attrs becomes RawAttrs (typed string-valued shape of the same canonical names) so element.attrs.testTag autocompletes. --- pkg/spec/src/index.ts | 3 +++ pkg/spec/src/types.ts | 54 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/pkg/spec/src/index.ts b/pkg/spec/src/index.ts index e60355f..39f9f46 100644 --- a/pkg/spec/src/index.ts +++ b/pkg/spec/src/index.ts @@ -3,15 +3,18 @@ export type { AccessibilityTree, Action, ActionGenerator, + AttrSelector, EventuallyFormula, ExceptionRecord, Extracted, Formula, InputTextAction, Key, + KnownAttrSelectors, LogEntry, Point, PressKeyAction, + RawAttrs, Sampler, SelectorPath, Snapshots, diff --git a/pkg/spec/src/types.ts b/pkg/spec/src/types.ts index a3c53ea..a72eb3d 100644 --- a/pkg/spec/src/types.ts +++ b/pkg/spec/src/types.ts @@ -1,8 +1,58 @@ export type Snapshots = Record; -export type AttrSelector = Record; + +/** + * Attribute names with known canonical types. Cross-platform aliases (e.g. + * `testTag` -> resource-id / accessibilityIdentifier) are listed so authors + * get autocomplete on whichever name they prefer. + * + * Boolean state attributes accept a native boolean; the runtime stringifies + * to "true"/"false" before matching. + */ +export interface KnownAttrSelectors { + testTag?: string; + identifier?: string; + accessibilityIdentifier?: string; + "resource-id"?: string; + + "content-desc"?: string; + accessibilityText?: string; + accessibilityLabel?: string; + label?: string; + + text?: string; + class?: string; + elementType?: string; + package?: string; + placeholderValue?: string; + hintText?: string; + + clickable?: boolean; + enabled?: boolean; + focused?: boolean; + checked?: boolean; + selected?: boolean; +} + +/** + * Object-form selector for `find` / `findAll`. Known attributes are typed + * via `KnownAttrSelectors`; arbitrary string keys are still allowed for + * raw driver attributes the typed surface doesn't yet cover. + */ +export type AttrSelector = KnownAttrSelectors & { + [key: string]: string | boolean | undefined; +}; export type SelectorPath = readonly AttrSelector[]; +/** String-valued attribute names with known canonical keys. */ +export type RawAttrs = { + [K in keyof KnownAttrSelectors]?: KnownAttrSelectors[K] extends boolean | undefined + ? "true" | "false" + : string; +} & { + [key: string]: string | undefined; +}; + export interface AccessibilityElement { id?: string; text?: string; @@ -16,7 +66,7 @@ export interface AccessibilityElement { bounds?: { left: number; top: number; right: number; bottom: number }; x?: number; y?: number; - attrs?: Record; + attrs?: RawAttrs; find(selector: string | AttrSelector | SelectorPath): AccessibilityElement | undefined; findAll(selector: string | AttrSelector | SelectorPath): AccessibilityElement[]; }