1use std::process::Stdio;
4
5use super::{Device, Result, Validate};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub enum Appearance {
10 Light,
12
13 Dark,
15
16 Custom(String),
19}
20
21#[derive(Clone, Debug)]
23pub struct UI {
24 device: Device,
25}
26
27impl Device {
28 pub fn ui(&self) -> UI {
30 UI {
31 device: self.clone(),
32 }
33 }
34}
35
36impl UI {
37 pub fn appearance(&self) -> Result<Appearance> {
41 let output = self
42 .device
43 .simctl()
44 .command("ui")
45 .arg(&self.device.udid)
46 .arg("appearance")
47 .stdout(Stdio::piped())
48 .output()?;
49
50 let output = output.validate_with_output()?;
51
52 let appearance = String::from_utf8(output.stdout)?.trim().to_owned();
53 Ok(match appearance.as_str() {
54 "light" => Appearance::Light,
55 "dark" => Appearance::Dark,
56 _ => Appearance::Custom(appearance),
57 })
58 }
59
60 pub fn set_appearance(&self, appearance: Appearance) -> Result<()> {
62 let appearance = match &appearance {
63 Appearance::Light => "light",
64 Appearance::Dark => "dark",
65 Appearance::Custom(appearance) => appearance,
66 };
67
68 self.device
69 .simctl()
70 .command("ui")
71 .arg(&self.device.udid)
72 .arg("appearance")
73 .arg(appearance)
74 .output()?
75 .validate()
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use serial_test::serial;
82
83 use super::*;
84 use crate::mock;
85
86 #[test]
87 #[serial]
88 fn test_appearance() -> Result<()> {
89 mock::device()?.boot()?;
90
91 mock::device()?.ui().set_appearance(Appearance::Dark)?;
92 assert_eq!(mock::device()?.ui().appearance()?, Appearance::Dark);
93
94 mock::device()?.ui().set_appearance(Appearance::Light)?;
95 assert_eq!(mock::device()?.ui().appearance()?, Appearance::Light);
96
97 mock::device()?.shutdown()?;
98
99 Ok(())
100 }
101}