1use serde::Serialize;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
17#[serde(rename_all = "lowercase")]
18#[non_exhaustive]
19pub enum MouseButton {
20 Left,
22 Right,
24 Middle,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
38#[non_exhaustive]
39pub enum KeyboardModifier {
40 Alt,
42 Control,
44 Meta,
46 Shift,
48 ControlOrMeta,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
64pub struct Position {
65 pub x: f64,
67 pub y: f64,
69}
70
71#[derive(Debug, Clone, Default, serde::Serialize)]
101#[serde(rename_all = "camelCase")]
102#[non_exhaustive]
103pub struct ClickOptions {
104 #[serde(skip_serializing_if = "Option::is_none")]
106 pub button: Option<MouseButton>,
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub click_count: Option<u32>,
110 #[serde(skip_serializing_if = "Option::is_none")]
112 pub delay: Option<f64>,
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub force: Option<bool>,
116 #[serde(skip_serializing_if = "Option::is_none")]
118 pub modifiers: Option<Vec<KeyboardModifier>>,
119 #[serde(skip_serializing_if = "Option::is_none")]
121 pub no_wait_after: Option<bool>,
122 #[serde(skip_serializing_if = "Option::is_none")]
124 pub position: Option<Position>,
125 #[serde(serialize_with = "crate::protocol::serialize_timeout_or_default")]
128 pub timeout: Option<f64>,
129 #[serde(skip_serializing_if = "Option::is_none")]
131 pub trial: Option<bool>,
132}
133
134impl ClickOptions {
135 pub fn builder() -> ClickOptionsBuilder {
137 ClickOptionsBuilder::default()
138 }
139
140 pub(crate) fn to_json(&self) -> serde_json::Value {
142 serde_json::to_value(self).expect("ClickOptions serialization cannot fail")
143 }
144}
145
146#[derive(Debug, Clone, Default)]
150pub struct ClickOptionsBuilder {
151 button: Option<MouseButton>,
152 click_count: Option<u32>,
153 delay: Option<f64>,
154 force: Option<bool>,
155 modifiers: Option<Vec<KeyboardModifier>>,
156 no_wait_after: Option<bool>,
157 position: Option<Position>,
158 timeout: Option<f64>,
159 trial: Option<bool>,
160}
161
162impl ClickOptionsBuilder {
163 pub fn button(mut self, button: MouseButton) -> Self {
165 self.button = Some(button);
166 self
167 }
168
169 pub fn click_count(mut self, click_count: u32) -> Self {
171 self.click_count = Some(click_count);
172 self
173 }
174
175 pub fn delay(mut self, delay: f64) -> Self {
177 self.delay = Some(delay);
178 self
179 }
180
181 pub fn force(mut self, force: bool) -> Self {
183 self.force = Some(force);
184 self
185 }
186
187 pub fn modifiers(mut self, modifiers: Vec<KeyboardModifier>) -> Self {
189 self.modifiers = Some(modifiers);
190 self
191 }
192
193 pub fn no_wait_after(mut self, no_wait_after: bool) -> Self {
195 self.no_wait_after = Some(no_wait_after);
196 self
197 }
198
199 pub fn position(mut self, position: Position) -> Self {
201 self.position = Some(position);
202 self
203 }
204
205 pub fn timeout(mut self, timeout: f64) -> Self {
207 self.timeout = Some(timeout);
208 self
209 }
210
211 pub fn trial(mut self, trial: bool) -> Self {
213 self.trial = Some(trial);
214 self
215 }
216
217 pub fn build(self) -> ClickOptions {
219 ClickOptions {
220 button: self.button,
221 click_count: self.click_count,
222 delay: self.delay,
223 force: self.force,
224 modifiers: self.modifiers,
225 no_wait_after: self.no_wait_after,
226 position: self.position,
227 timeout: self.timeout,
228 trial: self.trial,
229 }
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236
237 #[test]
238 fn test_mouse_button_serialization() {
239 assert_eq!(
240 serde_json::to_string(&MouseButton::Left).unwrap(),
241 "\"left\""
242 );
243 assert_eq!(
244 serde_json::to_string(&MouseButton::Right).unwrap(),
245 "\"right\""
246 );
247 assert_eq!(
248 serde_json::to_string(&MouseButton::Middle).unwrap(),
249 "\"middle\""
250 );
251 }
252
253 #[test]
254 fn test_keyboard_modifier_serialization() {
255 assert_eq!(
256 serde_json::to_string(&KeyboardModifier::Alt).unwrap(),
257 "\"Alt\""
258 );
259 assert_eq!(
260 serde_json::to_string(&KeyboardModifier::Control).unwrap(),
261 "\"Control\""
262 );
263 assert_eq!(
264 serde_json::to_string(&KeyboardModifier::Meta).unwrap(),
265 "\"Meta\""
266 );
267 assert_eq!(
268 serde_json::to_string(&KeyboardModifier::Shift).unwrap(),
269 "\"Shift\""
270 );
271 assert_eq!(
272 serde_json::to_string(&KeyboardModifier::ControlOrMeta).unwrap(),
273 "\"ControlOrMeta\""
274 );
275 }
276
277 #[test]
278 fn test_builder_button() {
279 let options = ClickOptions::builder().button(MouseButton::Right).build();
280
281 let json = options.to_json();
282 assert_eq!(json["button"], "right");
283 }
284
285 #[test]
286 fn test_builder_click_count() {
287 let options = ClickOptions::builder().click_count(2).build();
288
289 let json = options.to_json();
290 assert_eq!(json["clickCount"], 2);
291 }
292
293 #[test]
294 fn test_builder_delay() {
295 let options = ClickOptions::builder().delay(100.0).build();
296
297 let json = options.to_json();
298 assert_eq!(json["delay"], 100.0);
299 }
300
301 #[test]
302 fn test_builder_force() {
303 let options = ClickOptions::builder().force(true).build();
304
305 let json = options.to_json();
306 assert_eq!(json["force"], true);
307 }
308
309 #[test]
310 fn test_builder_modifiers() {
311 let options = ClickOptions::builder()
312 .modifiers(vec![KeyboardModifier::Shift, KeyboardModifier::Control])
313 .build();
314
315 let json = options.to_json();
316 assert_eq!(json["modifiers"], serde_json::json!(["Shift", "Control"]));
317 }
318
319 #[test]
320 fn test_builder_position() {
321 let position = Position { x: 10.0, y: 20.0 };
322 let options = ClickOptions::builder().position(position).build();
323
324 let json = options.to_json();
325 assert_eq!(json["position"]["x"], 10.0);
326 assert_eq!(json["position"]["y"], 20.0);
327 }
328
329 #[test]
330 fn test_builder_timeout() {
331 let options = ClickOptions::builder().timeout(5000.0).build();
332
333 let json = options.to_json();
334 assert_eq!(json["timeout"], 5000.0);
335 }
336
337 #[test]
338 fn test_builder_trial() {
339 let options = ClickOptions::builder().trial(true).build();
340
341 let json = options.to_json();
342 assert_eq!(json["trial"], true);
343 }
344
345 #[test]
346 fn test_builder_multiple_options() {
347 let options = ClickOptions::builder()
348 .button(MouseButton::Right)
349 .modifiers(vec![KeyboardModifier::Shift])
350 .position(Position { x: 5.0, y: 10.0 })
351 .force(true)
352 .timeout(3000.0)
353 .build();
354
355 let json = options.to_json();
356 assert_eq!(json["button"], "right");
357 assert_eq!(json["modifiers"], serde_json::json!(["Shift"]));
358 assert_eq!(json["position"]["x"], 5.0);
359 assert_eq!(json["position"]["y"], 10.0);
360 assert_eq!(json["force"], true);
361 assert_eq!(json["timeout"], 3000.0);
362 }
363}