azizo_core/
mock.rs

1//! Mock controller for testing.
2
3use crate::controller::{AsusController, DisplayController};
4use crate::error::ControllerError;
5use crate::modes::{DisplayMode, EReadingMode, EyeCareMode, ManualMode, NormalMode, VividMode};
6use crate::state::ControllerState;
7use std::sync::Mutex;
8
9/// A mock display controller for testing.
10///
11/// This allows testing code that depends on [`DisplayController`] without
12/// requiring actual ASUS hardware or the ASUS DLL.
13///
14/// # Example
15///
16/// ```
17/// use asus_display_control::{MockController, DisplayController, NormalMode};
18///
19/// let mock = MockController::new();
20/// mock.set_mode(&NormalMode::new()).unwrap();
21/// assert_eq!(mock.get_state().mode_id, 1);
22/// ```
23pub struct MockController {
24    state: Mutex<ControllerState>,
25}
26
27impl MockController {
28    /// Create a new mock controller with default state.
29    pub fn new() -> Self {
30        Self {
31            state: Mutex::new(ControllerState {
32                mode_id: 1,
33                is_monochrome: false,
34                dimming: 70,
35                manual_slider: 50,
36                eyecare_level: 2,
37                ereading_grayscale: 3,
38                ereading_temp: 50,
39                last_non_ereading_mode: 1,
40            }),
41        }
42    }
43
44    /// Create a mock controller with custom initial state.
45    pub fn with_state(state: ControllerState) -> Self {
46        Self {
47            state: Mutex::new(state),
48        }
49    }
50}
51
52impl Default for MockController {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl DisplayController for MockController {
59    fn get_state(&self) -> ControllerState {
60        self.state.lock().unwrap().clone()
61    }
62
63    fn refresh_sliders(&self) -> Result<(), ControllerError> {
64        Ok(())
65    }
66
67    fn sync_all_sliders(&self) -> Result<(), ControllerError> {
68        Ok(())
69    }
70
71    fn set_dimming(&self, level: i32) -> Result<(), ControllerError> {
72        self.state.lock().unwrap().dimming = level.clamp(40, 100);
73        Ok(())
74    }
75
76    fn set_dimming_percent(&self, percent: i32) -> Result<(), ControllerError> {
77        let splendid_value = AsusController::percent_to_dimming(percent.clamp(0, 100));
78        self.set_dimming(splendid_value)
79    }
80
81    fn get_current_mode(&self) -> Result<Box<dyn DisplayMode>, ControllerError> {
82        let state = self.get_state();
83        match (state.mode_id, state.is_monochrome) {
84            (1, false) => Ok(Box::new(NormalMode::new())),
85            (2, false) => Ok(Box::new(VividMode::new())),
86            (6, false) => Ok(Box::new(ManualMode::from_controller_state(&state))),
87            (7, false) => Ok(Box::new(EyeCareMode::from_controller_state(&state))),
88            (_, true) => Ok(Box::new(EReadingMode::from_controller_state(&state))),
89            _ => Err(ControllerError::ModeNotDetected),
90        }
91    }
92
93    fn set_mode(&self, mode: &dyn DisplayMode) -> Result<(), ControllerError> {
94        let mut state = self.state.lock().unwrap();
95        if mode.is_ereading() {
96            state.last_non_ereading_mode = state.mode_id;
97            state.is_monochrome = true;
98        } else {
99            state.mode_id = mode.mode_id();
100            state.is_monochrome = false;
101        }
102        Ok(())
103    }
104
105    fn toggle_e_reading(&self) -> Result<Box<dyn DisplayMode>, ControllerError> {
106        let state = self.get_state();
107        if state.is_monochrome {
108            let restored: Box<dyn DisplayMode> = match state.last_non_ereading_mode {
109                2 => Box::new(VividMode::new()),
110                6 => Box::new(ManualMode::from_controller_state(&state)),
111                7 => Box::new(EyeCareMode::from_controller_state(&state)),
112                _ => Box::new(NormalMode::new()),
113            };
114            self.set_mode(&*restored)?;
115            Ok(restored)
116        } else {
117            let ereading = Box::new(EReadingMode::from_controller_state(&state));
118            self.set_mode(&*ereading)?;
119            Ok(ereading)
120        }
121    }
122}