creator_simctl/
status_bar.rs1use super::{Device, Result, Validate};
4
5#[derive(Clone, Debug, Eq, PartialEq)]
7pub enum BatteryState {
8 Charging,
10
11 Charged,
13
14 Discharging,
17}
18
19#[derive(Copy, Clone, Debug, Eq, PartialEq)]
21pub enum CellularMode {
22 NotSupported,
24
25 Searching,
27
28 Failed,
30
31 Active,
33}
34
35#[derive(Copy, Clone, Debug, Eq, PartialEq)]
37pub enum DataNetworkType {
38 Wifi,
40
41 Cell3G,
43
44 Cell4G,
46
47 CellLte,
49
50 CellLteA,
53
54 CellLtePlus,
56}
57
58#[derive(Copy, Clone, Debug, Eq, PartialEq)]
60pub enum WifiMode {
61 Searching,
63
64 Failed,
66
67 Active,
69}
70
71pub struct StatusBar {
73 device: Device,
74}
75
76impl StatusBar {
77 pub fn clear(&self) -> Result<()> {
79 self.device
80 .simctl()
81 .command("status_bar")
82 .arg(&self.device.udid)
83 .arg("clear")
84 .output()?
85 .validate()
86 }
87
88 pub fn empty_override(&self) -> StatusBarOverride {
90 StatusBarOverride {
91 device: self.device.clone(),
92 time: None,
93 data_network: None,
94 wifi_mode: None,
95 wifi_bars: None,
96 cellular_mode: None,
97 cellular_bars: None,
98 operator_name: None,
99 battery_state: None,
100 battery_level: None,
101 }
102 }
103}
104
105pub struct StatusBarOverride {
108 device: Device,
109 time: Option<String>,
110 data_network: Option<DataNetworkType>,
111 wifi_mode: Option<WifiMode>,
112 wifi_bars: Option<usize>,
113 cellular_mode: Option<CellularMode>,
114 cellular_bars: Option<usize>,
115 operator_name: Option<String>,
116 battery_state: Option<BatteryState>,
117 battery_level: Option<usize>,
118}
119
120impl StatusBarOverride {
121 pub fn time(&mut self, time: &str) -> &mut StatusBarOverride {
123 self.time = Some(time.to_owned());
124 self
125 }
126
127 pub fn data_network(&mut self, data_network: DataNetworkType) -> &mut StatusBarOverride {
130 self.data_network = Some(data_network);
131 self
132 }
133
134 pub fn wifi_mode(&mut self, wifi_mode: WifiMode) -> &mut StatusBarOverride {
137 self.wifi_mode = Some(wifi_mode);
138 self
139 }
140
141 pub fn wifi_bars(&mut self, wifi_bars: usize) -> &mut StatusBarOverride {
144 self.wifi_bars = Some(wifi_bars);
145 self
146 }
147
148 pub fn cellular_mode(&mut self, cellular_mode: CellularMode) -> &mut StatusBarOverride {
151 self.cellular_mode = Some(cellular_mode);
152 self
153 }
154
155 pub fn cellular_bars(&mut self, cellular_bars: usize) -> &mut StatusBarOverride {
159 self.cellular_bars = Some(cellular_bars);
160 self
161 }
162
163 pub fn operator_name(&mut self, name: &str) -> &mut StatusBarOverride {
166 self.operator_name = Some(name.to_owned());
167 self
168 }
169
170 pub fn battery_state(&mut self, state: BatteryState) -> &mut StatusBarOverride {
172 self.battery_state = Some(state);
173 self
174 }
175
176 pub fn battery_level(&mut self, level: usize) -> &mut StatusBarOverride {
179 self.battery_level = Some(level);
180 self
181 }
182
183 pub fn apply(&self) -> Result<()> {
185 let mut command = self.device.simctl().command("status_bar");
186
187 command.arg(&self.device.udid).arg("override");
188
189 if let Some(time) = self.time.as_ref() {
190 command.arg("--time").arg(time);
191 }
192
193 if let Some(network) = self.data_network.as_ref() {
194 command.arg("--dataNetwork").arg(match network {
195 DataNetworkType::Wifi => "wifi",
196 DataNetworkType::Cell3G => "3g",
197 DataNetworkType::Cell4G => "4g",
198 DataNetworkType::CellLte => "lte",
199 DataNetworkType::CellLteA => "lte-a",
200 DataNetworkType::CellLtePlus => "lte+",
201 });
202 }
203
204 if let Some(mode) = self.wifi_mode.as_ref() {
205 command.arg("--wifiMode").arg(match mode {
206 WifiMode::Searching => "searching",
207 WifiMode::Failed => "failed",
208 WifiMode::Active => "active",
209 });
210 }
211
212 if let Some(bars) = self.wifi_bars.as_ref() {
213 command.arg("--wifiBars").arg(bars.to_string());
214 }
215
216 if let Some(mode) = self.cellular_mode.as_ref() {
217 command.arg("--cellularMode").arg(match mode {
218 CellularMode::NotSupported => "notSupported",
219 CellularMode::Searching => "searching",
220 CellularMode::Failed => "failed",
221 CellularMode::Active => "active",
222 });
223 }
224
225 if let Some(bars) = self.cellular_bars.as_ref() {
226 command.arg("--cellularBars").arg(bars.to_string());
227 }
228
229 if let Some(name) = self.operator_name.as_ref() {
230 command.arg("--operatorName").arg(&name);
231 }
232
233 if let Some(state) = self.battery_state.as_ref() {
234 command.arg("--batteryState").arg(match state {
235 BatteryState::Charging => "charging",
236 BatteryState::Charged => "charged",
237 BatteryState::Discharging => "discharging",
238 });
239 }
240
241 if let Some(level) = self.battery_level.as_ref() {
242 command.arg("--batteryLevel").arg(level.to_string());
243 }
244
245 command.output()?.validate()
246 }
247}
248
249impl Device {
250 pub fn status_bar(&self) -> StatusBar {
252 StatusBar {
253 device: self.clone(),
254 }
255 }
256}
257
258#[cfg(test)]
259mod tests {
260 use serial_test::serial;
261
262 use super::*;
263 use crate::mock;
264
265 #[test]
266 #[serial]
267 fn test_status_bar() -> Result<()> {
268 mock::device()?.boot()?;
269 mock::device()?
270 .status_bar()
271 .empty_override()
272 .time("00:00")
273 .data_network(DataNetworkType::Cell4G)
274 .cellular_mode(CellularMode::Active)
275 .cellular_bars(3)
276 .operator_name("Babel")
277 .battery_state(BatteryState::Discharging)
278 .battery_level(42)
279 .apply()?;
280 mock::device()?.status_bar().clear()?;
281 mock::device()?.shutdown()?;
282
283 Ok(())
284 }
285}