Skip to main content

smix_driver/
ios.rs

1//! iOS `Driver` impl. Pure delegation layer onto the existing
2//! `IosDriver` (renamed from `SimctlDriver`) inherent methods in lib.rs.
3//!
4//! 26 trait methods → 26 1-line delegations. No new logic.
5
6use async_trait::async_trait;
7use std::time::Duration;
8
9use smix_error::ExpectationFailure;
10use smix_input::{KeyName, SwipeDirection};
11use smix_runner_client::{IncludeScope, OcrFrame, SystemPopup, TapMode};
12use smix_screen::A11yNode;
13use smix_selector::Selector;
14
15use crate::traits::{Driver, Platform};
16use crate::{IosDriver, Orientation};
17
18#[async_trait]
19impl Driver for IosDriver {
20    fn platform(&self) -> Platform {
21        Platform::Ios
22    }
23
24    fn as_ios_driver(&self) -> Option<&IosDriver> {
25        Some(self)
26    }
27
28    /// iOS impl: mutate the wrapped `HttpRunnerClient` so every
29    /// subsequent request carries the `App-Bundle-Id` header. Runner
30    /// side rebinds `XCUIApplication(bundleIdentifier:)` per request.
31    fn set_target_bundle_id(&mut self, bundle: &str) {
32        self.runner_mut().set_target_bundle_id(bundle);
33    }
34
35    /// iOS impl: mutate the wrapped client to send
36    /// `App-Activate: true` on every request.
37    fn set_auto_activate(&mut self, activate: bool) {
38        self.runner_mut().set_auto_activate(activate);
39    }
40
41    /// iOS impl: force key-event dispatch mode on the
42    /// wrapped client. Sends `Input-Dispatch-Mode: key-events` header
43    /// on every request; runner-side dispatches via daemon key events
44    /// instead of a11y-anchored XCUIElement.typeText.
45    fn set_force_key_events(&mut self, force: bool) {
46        use smix_runner_client::InputDispatchMode;
47        if force {
48            self.runner_mut()
49                .set_input_dispatch_mode(InputDispatchMode::KeyEvents);
50        }
51    }
52
53    /// iOS impl: attach / clear the `Session-Id` header on
54    /// every subsequent request. When set, the runner short-circuits
55    /// per-request activation and reuses the session-cached
56    /// XCUIApplication binding.
57    fn set_session_id(&mut self, id: Option<String>) {
58        match id {
59            Some(sid) => self.runner_mut().set_session_id(sid),
60            None => self.runner_mut().clear_session_id(),
61        }
62    }
63
64    // === Sense ===
65
66    async fn tree(&self, include: Option<IncludeScope>) -> Result<A11yNode, ExpectationFailure> {
67        IosDriver::tree(self, include).await
68    }
69
70    async fn find(
71        &self,
72        selector: &Selector,
73        include: Option<IncludeScope>,
74    ) -> Result<bool, ExpectationFailure> {
75        IosDriver::find(self, selector, include).await
76    }
77
78    async fn find_one(
79        &self,
80        selector: &Selector,
81        include: Option<IncludeScope>,
82    ) -> Result<Option<A11yNode>, ExpectationFailure> {
83        IosDriver::find_one(self, selector, include).await
84    }
85
86    async fn find_all(
87        &self,
88        selector: &Selector,
89        include: Option<IncludeScope>,
90    ) -> Result<Vec<A11yNode>, ExpectationFailure> {
91        IosDriver::find_all(self, selector, include).await
92    }
93
94    async fn find_norm_coord(
95        &self,
96        selector: &Selector,
97    ) -> Result<Option<(f64, f64)>, ExpectationFailure> {
98        IosDriver::find_norm_coord(self, selector).await
99    }
100
101    async fn find_text_by_ocr(
102        &self,
103        text: &str,
104        locales: &[String],
105        recognition_level: &str,
106    ) -> Result<Option<OcrFrame>, ExpectationFailure> {
107        IosDriver::find_text_by_ocr(self, text, locales, recognition_level).await
108    }
109
110    async fn system_popups(
111        &self,
112        include: Option<IncludeScope>,
113    ) -> Result<Vec<SystemPopup>, ExpectationFailure> {
114        IosDriver::system_popups(self, include).await
115    }
116
117    async fn system_popup_action(
118        &self,
119        popup_id: &str,
120        button_id: &str,
121    ) -> Result<bool, ExpectationFailure> {
122        IosDriver::system_popup_action(self, popup_id, button_id).await
123    }
124
125    async fn wait_for(
126        &self,
127        selector: &Selector,
128        timeout: Duration,
129        include: Option<IncludeScope>,
130    ) -> Result<A11yNode, ExpectationFailure> {
131        IosDriver::wait_for(self, selector, timeout, include).await
132    }
133
134    // === Act ===
135
136    async fn tap(
137        &self,
138        selector: &Selector,
139        include: Option<IncludeScope>,
140    ) -> Result<crate::ActOutcome, ExpectationFailure> {
141        IosDriver::tap(self, selector, include).await
142    }
143
144    async fn tap_burst(
145        &self,
146        selector: &Selector,
147        times: u32,
148        interval_ms: Option<u32>,
149        hold_ms: Option<u32>,
150        include: Option<IncludeScope>,
151    ) -> Result<(), ExpectationFailure> {
152        IosDriver::tap_burst(self, selector, times, interval_ms, hold_ms, include).await
153    }
154
155    async fn tap_with_mode(
156        &self,
157        selector: &Selector,
158        mode: TapMode,
159        include: Option<IncludeScope>,
160    ) -> Result<(), ExpectationFailure> {
161        IosDriver::tap_with_mode(self, selector, mode, include).await
162    }
163
164    async fn tap_at_norm_coord(&self, nx: f64, ny: f64) -> Result<(), ExpectationFailure> {
165        IosDriver::tap_at_norm_coord(self, nx, ny).await
166    }
167
168    async fn tap_by_id(&self, id: &str) -> Result<(), ExpectationFailure> {
169        IosDriver::tap_by_id(self, id).await
170    }
171
172    async fn double_tap(
173        &self,
174        selector: &Selector,
175        include: Option<IncludeScope>,
176    ) -> Result<(), ExpectationFailure> {
177        IosDriver::double_tap(self, selector, include).await
178    }
179
180    async fn long_press(
181        &self,
182        selector: &Selector,
183        duration: Duration,
184        include: Option<IncludeScope>,
185    ) -> Result<crate::PressTiming, ExpectationFailure> {
186        IosDriver::long_press(self, selector, duration, include).await
187    }
188
189    async fn fill(
190        &self,
191        selector: &Selector,
192        text: &str,
193        include: Option<IncludeScope>,
194    ) -> Result<(), ExpectationFailure> {
195        IosDriver::fill(self, selector, text, include).await
196    }
197
198    async fn clear(
199        &self,
200        selector: &Selector,
201        include: Option<IncludeScope>,
202    ) -> Result<(), ExpectationFailure> {
203        IosDriver::clear(self, selector, include).await
204    }
205
206    async fn press_key(&self, key: KeyName) -> Result<(), ExpectationFailure> {
207        IosDriver::press_key(self, key).await
208    }
209
210    async fn scroll(
211        &self,
212        selector: &Selector,
213        direction: SwipeDirection,
214    ) -> Result<(), ExpectationFailure> {
215        IosDriver::scroll(self, selector, direction).await
216    }
217
218    async fn swipe_once(&self, direction: SwipeDirection) -> Result<(), ExpectationFailure> {
219        IosDriver::swipe_once(self, direction).await
220    }
221
222    async fn swipe_at_norm_coord(
223        &self,
224        from: (f64, f64),
225        to: (f64, f64),
226    ) -> Result<(), ExpectationFailure> {
227        IosDriver::swipe_at_norm_coord(self, from, to).await
228    }
229
230    async fn hide_keyboard(&self) -> Result<(), ExpectationFailure> {
231        IosDriver::hide_keyboard(self).await
232    }
233
234    async fn back(&self) -> Result<(), ExpectationFailure> {
235        IosDriver::back(self).await
236    }
237
238    async fn set_orientation(&self, orientation: Orientation) -> Result<(), ExpectationFailure> {
239        IosDriver::set_orientation(self, orientation).await
240    }
241
242    async fn foreground(&self, bundle_id: &str) -> Result<(), ExpectationFailure> {
243        IosDriver::foreground(self, bundle_id).await
244    }
245
246    async fn webview_eval(&self, js: &str) -> Result<serde_json::Value, ExpectationFailure> {
247        IosDriver::webview_eval(self, js).await
248    }
249}