mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 20:30:47 +02:00
feat(ios-qa): add XCUITest execution-plan module
Standalone planner that turns the IOSQAFlow JSON contract into an xcodebuild XCUITest invocation for simulator or physical device, using semantic selectors (identifier/role/label) and no coordinate taps. Pure plan generation; covered by 7 unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
a84a6e233d
commit
466b1ec744
@@ -0,0 +1,77 @@
|
||||
export type IOSQATarget =
|
||||
| { kind: 'simulator'; udid: string }
|
||||
| { kind: 'device'; udid: string };
|
||||
|
||||
export type ElementRole =
|
||||
| 'button'
|
||||
| 'cell'
|
||||
| 'link'
|
||||
| 'navigationBar'
|
||||
| 'secureTextField'
|
||||
| 'staticText'
|
||||
| 'switch'
|
||||
| 'textField';
|
||||
|
||||
export interface ElementSelector {
|
||||
/** Stable accessibility identifiers are always attempted before fallback fields. */
|
||||
identifier?: string;
|
||||
label?: string;
|
||||
role?: ElementRole;
|
||||
}
|
||||
|
||||
export type Verification =
|
||||
| { kind: 'exists'; selector: ElementSelector; timeoutMs?: number }
|
||||
| { kind: 'notExists'; selector: ElementSelector; timeoutMs?: number }
|
||||
| { kind: 'labelEquals'; selector: ElementSelector; value: string; timeoutMs?: number };
|
||||
|
||||
export type FlowStep =
|
||||
| { id: string; action: 'launch'; arguments?: string[]; environment?: Record<string, string>; verify?: Verification }
|
||||
| { id: string; action: 'tap'; selector: ElementSelector; timeoutMs?: number; verify?: Verification }
|
||||
| { id: string; action: 'typeText'; selector: ElementSelector; text: string; clear?: boolean; timeoutMs?: number; verify?: Verification }
|
||||
| { id: string; action: 'swipe'; direction: 'up' | 'down' | 'left' | 'right'; selector?: ElementSelector; verify?: Verification }
|
||||
| { id: string; action: 'wait'; verification: Verification };
|
||||
|
||||
export interface IOSQAFlow {
|
||||
version: 1;
|
||||
name: string;
|
||||
bundleIdentifier?: string;
|
||||
steps: FlowStep[];
|
||||
}
|
||||
|
||||
export interface XCUITestRunnerConfig {
|
||||
projectPath?: string;
|
||||
workspacePath?: string;
|
||||
scheme: string;
|
||||
testIdentifier: string;
|
||||
derivedDataPath?: string;
|
||||
resultBundlePath?: string;
|
||||
}
|
||||
|
||||
export interface ExecutorCapabilities {
|
||||
semanticSelectors: readonly ['identifier', 'role', 'label'];
|
||||
actions: readonly ['launch', 'tap', 'typeText', 'swipe', 'wait'];
|
||||
targets: readonly ['simulator', 'device'];
|
||||
coordinateTaps: false;
|
||||
postActionVerification: true;
|
||||
}
|
||||
|
||||
export const XCUITEST_CAPABILITIES: ExecutorCapabilities = {
|
||||
semanticSelectors: ['identifier', 'role', 'label'],
|
||||
actions: ['launch', 'tap', 'typeText', 'swipe', 'wait'],
|
||||
targets: ['simulator', 'device'],
|
||||
coordinateTaps: false,
|
||||
postActionVerification: true,
|
||||
};
|
||||
|
||||
export type PlanResult =
|
||||
| { status: 'ready'; plan: XCUITestExecutionPlan }
|
||||
| { status: 'blocked'; reason: string; remediation: string }
|
||||
| { status: 'unsupported'; reason: string; stepId?: string };
|
||||
|
||||
export interface XCUITestExecutionPlan {
|
||||
backend: 'xcuitest';
|
||||
target: IOSQATarget;
|
||||
capabilities: ExecutorCapabilities;
|
||||
command: { executable: 'xcodebuild'; args: string[]; env: Record<string, string> };
|
||||
flow: IOSQAFlow;
|
||||
}
|
||||
Reference in New Issue
Block a user