firefox_webdriver/driver/profile/
preferences.rs1#[derive(Debug, Clone, PartialEq, Eq, Hash)]
38pub enum PreferenceValue {
39 Bool(bool),
41
42 Int(i32),
44
45 String(String),
47}
48
49impl PreferenceValue {
54 #[must_use]
60 pub fn to_js_string(&self) -> String {
61 match self {
62 Self::Bool(b) => b.to_string(),
63 Self::Int(i) => i.to_string(),
64 Self::String(s) => format!("\"{}\"", escape_js_string(s)),
65 }
66 }
67}
68
69impl From<bool> for PreferenceValue {
74 #[inline]
75 fn from(value: bool) -> Self {
76 Self::Bool(value)
77 }
78}
79
80impl From<i32> for PreferenceValue {
81 #[inline]
82 fn from(value: i32) -> Self {
83 Self::Int(value)
84 }
85}
86
87impl From<String> for PreferenceValue {
88 #[inline]
89 fn from(value: String) -> Self {
90 Self::String(value)
91 }
92}
93
94impl From<&str> for PreferenceValue {
95 #[inline]
96 fn from(value: &str) -> Self {
97 Self::String(value.to_string())
98 }
99}
100
101#[derive(Debug, Clone)]
120pub struct FirefoxPreference {
121 pub key: String,
123
124 pub value: PreferenceValue,
126
127 pub comment: Option<String>,
129}
130
131impl FirefoxPreference {
136 #[must_use]
143 pub fn new(key: impl Into<String>, value: impl Into<PreferenceValue>) -> Self {
144 Self {
145 key: key.into(),
146 value: value.into(),
147 comment: None,
148 }
149 }
150
151 #[must_use]
159 pub fn with_comment(mut self, comment: impl Into<String>) -> Self {
160 self.comment = Some(comment.into());
161 self
162 }
163
164 #[must_use]
175 pub fn to_user_pref_line(&self) -> String {
176 let mut output = String::new();
177
178 if let Some(comment) = &self.comment {
179 output.push_str("// ");
180 output.push_str(comment);
181 output.push('\n');
182 }
183
184 output.push_str(&format!(
185 "user_pref(\"{}\", {});",
186 self.key,
187 self.value.to_js_string()
188 ));
189
190 output
191 }
192}
193
194fn escape_js_string(s: &str) -> String {
200 s.replace('\\', "\\\\")
201 .replace('"', "\\\"")
202 .replace('\n', "\\n")
203 .replace('\r', "\\r")
204 .replace('\t', "\\t")
205}
206
207#[cfg(test)]
212mod tests {
213 use super::{FirefoxPreference, PreferenceValue, escape_js_string};
214
215 #[test]
220 fn test_bool_to_js_string() {
221 assert_eq!(PreferenceValue::Bool(true).to_js_string(), "true");
222 assert_eq!(PreferenceValue::Bool(false).to_js_string(), "false");
223 }
224
225 #[test]
226 fn test_int_to_js_string() {
227 assert_eq!(PreferenceValue::Int(42).to_js_string(), "42");
228 assert_eq!(PreferenceValue::Int(-10).to_js_string(), "-10");
229 assert_eq!(PreferenceValue::Int(0).to_js_string(), "0");
230 }
231
232 #[test]
233 fn test_string_to_js_string() {
234 assert_eq!(
235 PreferenceValue::String("test".to_string()).to_js_string(),
236 "\"test\""
237 );
238 assert_eq!(
239 PreferenceValue::String(String::new()).to_js_string(),
240 "\"\""
241 );
242 }
243
244 #[test]
245 fn test_from_bool() {
246 let val: PreferenceValue = true.into();
247 assert_eq!(val, PreferenceValue::Bool(true));
248 }
249
250 #[test]
251 fn test_from_i32() {
252 let val: PreferenceValue = 42.into();
253 assert_eq!(val, PreferenceValue::Int(42));
254 }
255
256 #[test]
257 fn test_from_string() {
258 let val: PreferenceValue = String::from("test").into();
259 assert_eq!(val, PreferenceValue::String("test".to_string()));
260 }
261
262 #[test]
263 fn test_from_str() {
264 let val: PreferenceValue = "test".into();
265 assert_eq!(val, PreferenceValue::String("test".to_string()));
266 }
267
268 #[test]
273 fn test_escape_backslash() {
274 assert_eq!(escape_js_string("path\\to\\file"), "path\\\\to\\\\file");
275 }
276
277 #[test]
278 fn test_escape_quotes() {
279 assert_eq!(escape_js_string("with\"quotes"), "with\\\"quotes");
280 }
281
282 #[test]
283 fn test_escape_newline() {
284 assert_eq!(escape_js_string("line1\nline2"), "line1\\nline2");
285 }
286
287 #[test]
288 fn test_escape_carriage_return() {
289 assert_eq!(escape_js_string("line1\rline2"), "line1\\rline2");
290 }
291
292 #[test]
293 fn test_escape_tab() {
294 assert_eq!(escape_js_string("col1\tcol2"), "col1\\tcol2");
295 }
296
297 #[test]
298 fn test_escape_combined() {
299 assert_eq!(
300 escape_js_string("path\\to\n\"file\""),
301 "path\\\\to\\n\\\"file\\\""
302 );
303 }
304
305 #[test]
310 fn test_new_preference() {
311 let pref = FirefoxPreference::new("test.pref", PreferenceValue::Bool(true));
312 assert_eq!(pref.key, "test.pref");
313 assert_eq!(pref.value, PreferenceValue::Bool(true));
314 assert!(pref.comment.is_none());
315 }
316
317 #[test]
318 fn test_with_comment() {
319 let pref = FirefoxPreference::new("test.pref", PreferenceValue::Int(42))
320 .with_comment("Test comment");
321
322 assert_eq!(pref.comment, Some("Test comment".to_string()));
323 }
324
325 #[test]
326 fn test_to_user_pref_line_bool() {
327 let pref = FirefoxPreference::new("test.pref", PreferenceValue::Bool(true));
328 assert_eq!(pref.to_user_pref_line(), "user_pref(\"test.pref\", true);");
329 }
330
331 #[test]
332 fn test_to_user_pref_line_int() {
333 let pref = FirefoxPreference::new("test.pref", PreferenceValue::Int(42));
334 assert_eq!(pref.to_user_pref_line(), "user_pref(\"test.pref\", 42);");
335 }
336
337 #[test]
338 fn test_to_user_pref_line_string() {
339 let pref = FirefoxPreference::new("test.pref", PreferenceValue::String("value".into()));
340 assert_eq!(
341 pref.to_user_pref_line(),
342 "user_pref(\"test.pref\", \"value\");"
343 );
344 }
345
346 #[test]
347 fn test_to_user_pref_line_with_comment() {
348 let pref = FirefoxPreference::new("test.pref", PreferenceValue::Int(42))
349 .with_comment("Test preference");
350
351 let line = pref.to_user_pref_line();
352 assert!(line.starts_with("// Test preference\n"));
353 assert!(line.ends_with("user_pref(\"test.pref\", 42);"));
354 }
355
356 #[test]
357 fn test_new_with_into_value() {
358 let pref = FirefoxPreference::new("test.bool", false);
360 assert_eq!(pref.value, PreferenceValue::Bool(false));
361
362 let pref = FirefoxPreference::new("test.int", 123);
363 assert_eq!(pref.value, PreferenceValue::Int(123));
364 }
365
366 #[test]
367 fn test_preference_clone() {
368 let pref = FirefoxPreference::new("test.pref", true).with_comment("comment");
369 let cloned = pref.clone();
370
371 assert_eq!(pref.key, cloned.key);
372 assert_eq!(pref.value, cloned.value);
373 assert_eq!(pref.comment, cloned.comment);
374 }
375}