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"] = serde_json::to_value(button).unwrap();
132 }
133
134 if let Some(click_count) = self.click_count {
135 json["clickCount"] = serde_json::json!(click_count);
136 }
137
138 if let Some(delay) = self.delay {
139 json["delay"] = serde_json::json!(delay);
140 }
141
142 if let Some(force) = self.force {
143 json["force"] = serde_json::json!(force);
144 }
145
146 if let Some(modifiers) = &self.modifiers {
147 json["modifiers"] = serde_json::to_value(modifiers).unwrap();
148 }
149
150 if let Some(no_wait_after) = self.no_wait_after {
151 json["noWaitAfter"] = serde_json::json!(no_wait_after);
152 }
153
154 if let Some(position) = &self.position {
155 json["position"] = serde_json::to_value(position).unwrap();
156 }
157
158 if let Some(timeout) = self.timeout {
160 json["timeout"] = serde_json::json!(timeout);
161 } else {
162 json["timeout"] = serde_json::json!(crate::DEFAULT_TIMEOUT_MS);
163 }
164
165 if let Some(trial) = self.trial {
166 json["trial"] = serde_json::json!(trial);
167 }
168
169 json
170 }
171}
172
173#[derive(Debug, Clone, Default)]
177pub struct ClickOptionsBuilder {
178 button: Option<MouseButton>,
179 click_count: Option<u32>,
180 delay: Option<f64>,
181 force: Option<bool>,
182 modifiers: Option<Vec<KeyboardModifier>>,
183 no_wait_after: Option<bool>,
184 position: Option<Position>,
185 timeout: Option<f64>,
186 trial: Option<bool>,
187}
188
189impl ClickOptionsBuilder {
190 pub fn button(mut self, button: MouseButton) -> Self {
192 self.button = Some(button);
193 self
194 }
195
196 pub fn click_count(mut self, click_count: u32) -> Self {
198 self.click_count = Some(click_count);
199 self
200 }
201
202 pub fn delay(mut self, delay: f64) -> Self {
204 self.delay = Some(delay);
205 self
206 }
207
208 pub fn force(mut self, force: bool) -> Self {
210 self.force = Some(force);
211 self
212 }
213
214 pub fn modifiers(mut self, modifiers: Vec<KeyboardModifier>) -> Self {
216 self.modifiers = Some(modifiers);
217 self
218 }
219
220 pub fn no_wait_after(mut self, no_wait_after: bool) -> Self {
222 self.no_wait_after = Some(no_wait_after);
223 self
224 }
225
226 pub fn position(mut self, position: Position) -> Self {
228 self.position = Some(position);
229 self
230 }
231
232 pub fn timeout(mut self, timeout: f64) -> Self {
234 self.timeout = Some(timeout);
235 self
236 }
237
238 pub fn trial(mut self, trial: bool) -> Self {
240 self.trial = Some(trial);
241 self
242 }
243
244 pub fn build(self) -> ClickOptions {
246 ClickOptions {
247 button: self.button,
248 click_count: self.click_count,
249 delay: self.delay,
250 force: self.force,
251 modifiers: self.modifiers,
252 no_wait_after: self.no_wait_after,
253 position: self.position,
254 timeout: self.timeout,
255 trial: self.trial,
256 }
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263
264 #[test]
265 fn test_mouse_button_serialization() {
266 assert_eq!(
267 serde_json::to_string(&MouseButton::Left).unwrap(),
268 "\"left\""
269 );
270 assert_eq!(
271 serde_json::to_string(&MouseButton::Right).unwrap(),
272 "\"right\""
273 );
274 assert_eq!(
275 serde_json::to_string(&MouseButton::Middle).unwrap(),
276 "\"middle\""
277 );
278 }
279
280 #[test]
281 fn test_keyboard_modifier_serialization() {
282 assert_eq!(
283 serde_json::to_string(&KeyboardModifier::Alt).unwrap(),
284 "\"Alt\""
285 );
286 assert_eq!(
287 serde_json::to_string(&KeyboardModifier::Control).unwrap(),
288 "\"Control\""
289 );
290 assert_eq!(
291 serde_json::to_string(&KeyboardModifier::Meta).unwrap(),
292 "\"Meta\""
293 );
294 assert_eq!(
295 serde_json::to_string(&KeyboardModifier::Shift).unwrap(),
296 "\"Shift\""
297 );
298 assert_eq!(
299 serde_json::to_string(&KeyboardModifier::ControlOrMeta).unwrap(),
300 "\"ControlOrMeta\""
301 );
302 }
303
304 #[test]
305 fn test_builder_button() {
306 let options = ClickOptions::builder().button(MouseButton::Right).build();
307
308 let json = options.to_json();
309 assert_eq!(json["button"], "right");
310 }
311
312 #[test]
313 fn test_builder_click_count() {
314 let options = ClickOptions::builder().click_count(2).build();
315
316 let json = options.to_json();
317 assert_eq!(json["clickCount"], 2);
318 }
319
320 #[test]
321 fn test_builder_delay() {
322 let options = ClickOptions::builder().delay(100.0).build();
323
324 let json = options.to_json();
325 assert_eq!(json["delay"], 100.0);
326 }
327
328 #[test]
329 fn test_builder_force() {
330 let options = ClickOptions::builder().force(true).build();
331
332 let json = options.to_json();
333 assert_eq!(json["force"], true);
334 }
335
336 #[test]
337 fn test_builder_modifiers() {
338 let options = ClickOptions::builder()
339 .modifiers(vec![KeyboardModifier::Shift, KeyboardModifier::Control])
340 .build();
341
342 let json = options.to_json();
343 assert_eq!(json["modifiers"], serde_json::json!(["Shift", "Control"]));
344 }
345
346 #[test]
347 fn test_builder_position() {
348 let position = Position { x: 10.0, y: 20.0 };
349 let options = ClickOptions::builder().position(position).build();
350
351 let json = options.to_json();
352 assert_eq!(json["position"]["x"], 10.0);
353 assert_eq!(json["position"]["y"], 20.0);
354 }
355
356 #[test]
357 fn test_builder_timeout() {
358 let options = ClickOptions::builder().timeout(5000.0).build();
359
360 let json = options.to_json();
361 assert_eq!(json["timeout"], 5000.0);
362 }
363
364 #[test]
365 fn test_builder_trial() {
366 let options = ClickOptions::builder().trial(true).build();
367
368 let json = options.to_json();
369 assert_eq!(json["trial"], true);
370 }
371
372 #[test]
373 fn test_builder_multiple_options() {
374 let options = ClickOptions::builder()
375 .button(MouseButton::Right)
376 .modifiers(vec![KeyboardModifier::Shift])
377 .position(Position { x: 5.0, y: 10.0 })
378 .force(true)
379 .timeout(3000.0)
380 .build();
381
382 let json = options.to_json();
383 assert_eq!(json["button"], "right");
384 assert_eq!(json["modifiers"], serde_json::json!(["Shift"]));
385 assert_eq!(json["position"]["x"], 5.0);
386 assert_eq!(json["position"]["y"], 10.0);
387 assert_eq!(json["force"], true);
388 assert_eq!(json["timeout"], 3000.0);
389 }
390}