browser_commander/browser/
media.rs1use crate::core::engine::EngineType;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum ColorScheme {
10 Light,
12 Dark,
14 NoPreference,
16}
17
18impl ColorScheme {
19 pub fn as_str(&self) -> &'static str {
21 match self {
22 ColorScheme::Light => "light",
23 ColorScheme::Dark => "dark",
24 ColorScheme::NoPreference => "no-preference",
25 }
26 }
27}
28
29impl std::fmt::Display for ColorScheme {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "{}", self.as_str())
32 }
33}
34
35impl std::str::FromStr for ColorScheme {
36 type Err = anyhow::Error;
37
38 fn from_str(s: &str) -> Result<Self, Self::Err> {
39 match s {
40 "light" => Ok(ColorScheme::Light),
41 "dark" => Ok(ColorScheme::Dark),
42 "no-preference" => Ok(ColorScheme::NoPreference),
43 _ => Err(anyhow::anyhow!(
44 "Invalid color scheme: \"{}\". Expected one of: light, dark, no-preference",
45 s
46 )),
47 }
48 }
49}
50
51#[derive(Debug, Clone)]
53pub struct EmulateMediaOptions {
54 pub color_scheme: Option<ColorScheme>,
56 pub engine: EngineType,
58}
59
60impl EmulateMediaOptions {
61 pub fn new(engine: EngineType, color_scheme: Option<ColorScheme>) -> Self {
63 Self {
64 color_scheme,
65 engine,
66 }
67 }
68
69 pub fn dark(engine: EngineType) -> Self {
71 Self::new(engine, Some(ColorScheme::Dark))
72 }
73
74 pub fn light(engine: EngineType) -> Self {
76 Self::new(engine, Some(ColorScheme::Light))
77 }
78
79 pub fn no_preference(engine: EngineType) -> Self {
81 Self::new(engine, Some(ColorScheme::NoPreference))
82 }
83
84 pub fn reset(engine: EngineType) -> Self {
86 Self::new(engine, None)
87 }
88}
89
90pub async fn emulate_media(options: EmulateMediaOptions) -> Result<(), anyhow::Error> {
116 match options.engine {
117 EngineType::Chromiumoxide
118 | EngineType::Fantoccini
119 | EngineType::Playwright
120 | EngineType::Puppeteer => {
121 tracing::debug!(
124 "emulate_media: engine={}, color_scheme={:?}",
125 options.engine,
126 options.color_scheme.as_ref().map(|cs| cs.as_str())
127 );
128 Ok(())
129 }
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use std::str::FromStr;
137
138 #[test]
139 fn color_scheme_as_str() {
140 assert_eq!(ColorScheme::Light.as_str(), "light");
141 assert_eq!(ColorScheme::Dark.as_str(), "dark");
142 assert_eq!(ColorScheme::NoPreference.as_str(), "no-preference");
143 }
144
145 #[test]
146 fn color_scheme_display() {
147 assert_eq!(ColorScheme::Light.to_string(), "light");
148 assert_eq!(ColorScheme::Dark.to_string(), "dark");
149 assert_eq!(ColorScheme::NoPreference.to_string(), "no-preference");
150 }
151
152 #[test]
153 fn color_scheme_from_str_valid() {
154 assert_eq!(ColorScheme::from_str("light").unwrap(), ColorScheme::Light);
155 assert_eq!(ColorScheme::from_str("dark").unwrap(), ColorScheme::Dark);
156 assert_eq!(
157 ColorScheme::from_str("no-preference").unwrap(),
158 ColorScheme::NoPreference
159 );
160 }
161
162 #[test]
163 fn color_scheme_from_str_invalid() {
164 assert!(ColorScheme::from_str("invalid").is_err());
165 assert!(ColorScheme::from_str("").is_err());
166 assert!(ColorScheme::from_str("DARK").is_err());
167 }
168
169 #[test]
170 fn emulate_media_options_dark() {
171 let opts = EmulateMediaOptions::dark(EngineType::Chromiumoxide);
172 assert_eq!(opts.color_scheme, Some(ColorScheme::Dark));
173 assert_eq!(opts.engine, EngineType::Chromiumoxide);
174 }
175
176 #[test]
177 fn emulate_media_options_light() {
178 let opts = EmulateMediaOptions::light(EngineType::Chromiumoxide);
179 assert_eq!(opts.color_scheme, Some(ColorScheme::Light));
180 }
181
182 #[test]
183 fn emulate_media_options_no_preference() {
184 let opts = EmulateMediaOptions::no_preference(EngineType::Chromiumoxide);
185 assert_eq!(opts.color_scheme, Some(ColorScheme::NoPreference));
186 }
187
188 #[test]
189 fn emulate_media_options_reset() {
190 let opts = EmulateMediaOptions::reset(EngineType::Chromiumoxide);
191 assert_eq!(opts.color_scheme, None);
192 }
193
194 #[tokio::test]
195 async fn emulate_media_chromiumoxide() {
196 let opts = EmulateMediaOptions::dark(EngineType::Chromiumoxide);
197 assert!(emulate_media(opts).await.is_ok());
198 }
199
200 #[tokio::test]
201 async fn emulate_media_fantoccini() {
202 let opts = EmulateMediaOptions::light(EngineType::Fantoccini);
203 assert!(emulate_media(opts).await.is_ok());
204 }
205}