1use serde::Serialize;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
17#[serde(rename_all = "lowercase")]
18pub enum MouseButton {
19 Left,
21 Right,
23 Middle,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
37pub enum KeyboardModifier {
38 Alt,
40 Control,
42 Meta,
44 Shift,
46 ControlOrMeta,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
62pub struct Position {
63 pub x: f64,
65 pub y: f64,
67}
68
69#[derive(Debug, Clone, Default)]
99pub struct ClickOptions {
100 pub button: Option<MouseButton>,
102 pub click_count: Option<u32>,
104 pub delay: Option<f64>,
106 pub force: Option<bool>,
108 pub modifiers: Option<Vec<KeyboardModifier>>,
110 pub no_wait_after: Option<bool>,
112 pub position: Option<Position>,
114 pub timeout: Option<f64>,
116 pub trial: Option<bool>,
118}
119
120impl ClickOptions {
121 pub fn builder() -> ClickOptionsBuilder {
123 ClickOptionsBuilder::default()
124 }
125
126 pub(crate) fn to_json(&self) -> serde_json::Value {
128 let mut json = serde_json::json!({});
129
130 if let Some(button) = &self.button {
131 json["button"] =
132 serde_json::to_value(button).expect("serialization of MouseButton cannot fail");
133 }
134
135 if let Some(click_count) = self.click_count {
136 json["clickCount"] = serde_json::json!(click_count);
137 }
138
139 if let Some(delay) = self.delay {
140 json["delay"] = serde_json::json!(delay);
141 }
142
143 if let Some(force) = self.force {
144 json["force"] = serde_json::json!(force);
145 }
146
147 if let Some(modifiers) = &self.modifiers {
148 json["modifiers"] =
149 serde_json::to_value(modifiers).expect("serialization of modifiers cannot fail");
150 }
151
152 if let Some(no_wait_after) = self.no_wait_after {
153 json["noWaitAfter"] = serde_json::json!(no_wait_after);
154 }
155
156 if let Some(position) = &self.position {
157 json["position"] =
158 serde_json::to_value(position).expect("serialization of position cannot fail");
159 }
160
161 if let Some(timeout) = self.timeout {
163 json["timeout"] = serde_json::json!(timeout);
164 } else {
165 json["timeout"] = serde_json::json!(crate::DEFAULT_TIMEOUT_MS);
166 }
167
168 if let Some(trial) = self.trial {
169 json["trial"] = serde_json::json!(trial);
170 }
171
172 json
173 }
174}
175
176#[derive(Debug, Clone, Default)]
180pub struct ClickOptionsBuilder {
181 button: Option<MouseButton>,
182 click_count: Option<u32>,
183 delay: Option<f64>,
184 force: Option<bool>,
185 modifiers: Option<Vec<KeyboardModifier>>,
186 no_wait_after: Option<bool>,
187 position: Option<Position>,
188 timeout: Option<f64>,
189 trial: Option<bool>,
190}
191
192impl ClickOptionsBuilder {
193 pub fn button(mut self, button: MouseButton) -> Self {
195 self.button = Some(button);
196 self
197 }
198
199 pub fn click_count(mut self, click_count: u32) -> Self {
201 self.click_count = Some(click_count);
202 self
203 }
204
205 pub fn delay(mut self, delay: f64) -> Self {
207 self.delay = Some(delay);
208 self
209 }
210
211 pub fn force(mut self, force: bool) -> Self {
213 self.force = Some(force);
214 self
215 }
216
217 pub fn modifiers(mut self, modifiers: Vec<KeyboardModifier>) -> Self {
219 self.modifiers = Some(modifiers);
220 self
221 }
222
223 pub fn no_wait_after(mut self, no_wait_after: bool) -> Self {
225 self.no_wait_after = Some(no_wait_after);
226 self
227 }
228
229 pub fn position(mut self, position: Position) -> Self {
231 self.position = Some(position);
232 self
233 }
234
235 pub fn timeout(mut self, timeout: f64) -> Self {
237 self.timeout = Some(timeout);
238 self
239 }
240
241 pub fn trial(mut self, trial: bool) -> Self {
243 self.trial = Some(trial);
244 self
245 }
246
247 pub fn build(self) -> ClickOptions {
249 ClickOptions {
250 button: self.button,
251 click_count: self.click_count,
252 delay: self.delay,
253 force: self.force,
254 modifiers: self.modifiers,
255 no_wait_after: self.no_wait_after,
256 position: self.position,
257 timeout: self.timeout,
258 trial: self.trial,
259 }
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 #[test]
268 fn test_mouse_button_serialization() {
269 assert_eq!(
270 serde_json::to_string(&MouseButton::Left).unwrap(),
271 "\"left\""
272 );
273 assert_eq!(
274 serde_json::to_string(&MouseButton::Right).unwrap(),
275 "\"right\""
276 );
277 assert_eq!(
278 serde_json::to_string(&MouseButton::Middle).unwrap(),
279 "\"middle\""
280 );
281 }
282
283 #[test]
284 fn test_keyboard_modifier_serialization() {
285 assert_eq!(
286 serde_json::to_string(&KeyboardModifier::Alt).unwrap(),
287 "\"Alt\""
288 );
289 assert_eq!(
290 serde_json::to_string(&KeyboardModifier::Control).unwrap(),
291 "\"Control\""
292 );
293 assert_eq!(
294 serde_json::to_string(&KeyboardModifier::Meta).unwrap(),
295 "\"Meta\""
296 );
297 assert_eq!(
298 serde_json::to_string(&KeyboardModifier::Shift).unwrap(),
299 "\"Shift\""
300 );
301 assert_eq!(
302 serde_json::to_string(&KeyboardModifier::ControlOrMeta).unwrap(),
303 "\"ControlOrMeta\""
304 );
305 }
306
307 #[test]
308 fn test_builder_button() {
309 let options = ClickOptions::builder().button(MouseButton::Right).build();
310
311 let json = options.to_json();
312 assert_eq!(json["button"], "right");
313 }
314
315 #[test]
316 fn test_builder_click_count() {
317 let options = ClickOptions::builder().click_count(2).build();
318
319 let json = options.to_json();
320 assert_eq!(json["clickCount"], 2);
321 }
322
323 #[test]
324 fn test_builder_delay() {
325 let options = ClickOptions::builder().delay(100.0).build();
326
327 let json = options.to_json();
328 assert_eq!(json["delay"], 100.0);
329 }
330
331 #[test]
332 fn test_builder_force() {
333 let options = ClickOptions::builder().force(true).build();
334
335 let json = options.to_json();
336 assert_eq!(json["force"], true);
337 }
338
339 #[test]
340 fn test_builder_modifiers() {
341 let options = ClickOptions::builder()
342 .modifiers(vec![KeyboardModifier::Shift, KeyboardModifier::Control])
343 .build();
344
345 let json = options.to_json();
346 assert_eq!(json["modifiers"], serde_json::json!(["Shift", "Control"]));
347 }
348
349 #[test]
350 fn test_builder_position() {
351 let position = Position { x: 10.0, y: 20.0 };
352 let options = ClickOptions::builder().position(position).build();
353
354 let json = options.to_json();
355 assert_eq!(json["position"]["x"], 10.0);
356 assert_eq!(json["position"]["y"], 20.0);
357 }
358
359 #[test]
360 fn test_builder_timeout() {
361 let options = ClickOptions::builder().timeout(5000.0).build();
362
363 let json = options.to_json();
364 assert_eq!(json["timeout"], 5000.0);
365 }
366
367 #[test]
368 fn test_builder_trial() {
369 let options = ClickOptions::builder().trial(true).build();
370
371 let json = options.to_json();
372 assert_eq!(json["trial"], true);
373 }
374
375 #[test]
376 fn test_builder_multiple_options() {
377 let options = ClickOptions::builder()
378 .button(MouseButton::Right)
379 .modifiers(vec![KeyboardModifier::Shift])
380 .position(Position { x: 5.0, y: 10.0 })
381 .force(true)
382 .timeout(3000.0)
383 .build();
384
385 let json = options.to_json();
386 assert_eq!(json["button"], "right");
387 assert_eq!(json["modifiers"], serde_json::json!(["Shift"]));
388 assert_eq!(json["position"]["x"], 5.0);
389 assert_eq!(json["position"]["y"], 10.0);
390 assert_eq!(json["force"], true);
391 assert_eq!(json["timeout"], 3000.0);
392 }
393}