1#![allow(clippy::unreadable_literal)]
12
13use std::collections::HashMap;
14
15#[derive(Debug, Clone, PartialEq)]
17pub struct GeolocationPosition {
18 pub latitude: f64,
20 pub longitude: f64,
22 pub accuracy: f64,
24 pub altitude: Option<f64>,
26 pub altitude_accuracy: Option<f64>,
28 pub heading: Option<f64>,
30 pub speed: Option<f64>,
32}
33
34impl GeolocationPosition {
35 #[must_use]
45 pub fn new(latitude: f64, longitude: f64, accuracy: f64) -> Self {
46 assert!(
47 (-90.0..=90.0).contains(&latitude),
48 "Latitude must be between -90 and 90 degrees"
49 );
50 assert!(
51 (-180.0..=180.0).contains(&longitude),
52 "Longitude must be between -180 and 180 degrees"
53 );
54 assert!(accuracy >= 0.0, "Accuracy must be non-negative");
55
56 Self {
57 latitude,
58 longitude,
59 accuracy,
60 altitude: None,
61 altitude_accuracy: None,
62 heading: None,
63 speed: None,
64 }
65 }
66
67 #[must_use]
69 pub fn with_altitude(mut self, altitude: f64, accuracy: f64) -> Self {
70 self.altitude = Some(altitude);
71 self.altitude_accuracy = Some(accuracy);
72 self
73 }
74
75 #[must_use]
77 pub fn with_heading(mut self, heading: f64) -> Self {
78 assert!(
79 (0.0..=360.0).contains(&heading),
80 "Heading must be between 0 and 360 degrees"
81 );
82 self.heading = Some(heading);
83 self
84 }
85
86 #[must_use]
88 pub fn with_speed(mut self, speed: f64) -> Self {
89 assert!(speed >= 0.0, "Speed must be non-negative");
90 self.speed = Some(speed);
91 self
92 }
93
94 #[must_use]
98 pub fn new_york() -> Self {
99 Self::new(40.758896, -73.985130, 10.0)
100 }
101
102 #[must_use]
104 pub fn tokyo() -> Self {
105 Self::new(35.659492, 139.700472, 10.0)
106 }
107
108 #[must_use]
110 pub fn london() -> Self {
111 Self::new(51.508039, -0.128069, 10.0)
112 }
113
114 #[must_use]
116 pub fn paris() -> Self {
117 Self::new(48.858370, 2.294481, 10.0)
118 }
119
120 #[must_use]
122 pub fn sydney() -> Self {
123 Self::new(-33.856784, 151.215297, 10.0)
124 }
125
126 #[must_use]
128 pub fn san_francisco() -> Self {
129 Self::new(37.820587, -122.478264, 10.0)
130 }
131
132 #[must_use]
134 pub fn berlin() -> Self {
135 Self::new(52.516275, 13.377704, 10.0)
136 }
137
138 #[must_use]
140 pub fn singapore() -> Self {
141 Self::new(1.283404, 103.860435, 10.0)
142 }
143
144 #[must_use]
146 pub fn dubai() -> Self {
147 Self::new(25.197197, 55.274376, 10.0)
148 }
149
150 #[must_use]
152 pub fn sao_paulo() -> Self {
153 Self::new(-23.561414, -46.655881, 10.0)
154 }
155}
156
157#[derive(Debug, Clone)]
159pub struct GeolocationMock {
160 current_position: Option<GeolocationPosition>,
162 presets: HashMap<String, GeolocationPosition>,
164 enabled: bool,
166 permission_granted: bool,
168 error_mode: Option<GeolocationError>,
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
174pub enum GeolocationError {
175 PermissionDenied,
177 PositionUnavailable,
179 Timeout,
181}
182
183impl Default for GeolocationMock {
184 fn default() -> Self {
185 Self::new()
186 }
187}
188
189impl GeolocationMock {
190 #[must_use]
192 pub fn new() -> Self {
193 let mut presets = HashMap::new();
194
195 presets.insert("new_york".to_string(), GeolocationPosition::new_york());
197 presets.insert("tokyo".to_string(), GeolocationPosition::tokyo());
198 presets.insert("london".to_string(), GeolocationPosition::london());
199 presets.insert("paris".to_string(), GeolocationPosition::paris());
200 presets.insert("sydney".to_string(), GeolocationPosition::sydney());
201 presets.insert(
202 "san_francisco".to_string(),
203 GeolocationPosition::san_francisco(),
204 );
205 presets.insert("berlin".to_string(), GeolocationPosition::berlin());
206 presets.insert("singapore".to_string(), GeolocationPosition::singapore());
207 presets.insert("dubai".to_string(), GeolocationPosition::dubai());
208 presets.insert("sao_paulo".to_string(), GeolocationPosition::sao_paulo());
209
210 Self {
211 current_position: None,
212 presets,
213 enabled: true,
214 permission_granted: true,
215 error_mode: None,
216 }
217 }
218
219 pub fn set_position(&mut self, position: GeolocationPosition) {
221 self.current_position = Some(position);
222 }
223
224 pub fn set_preset(&mut self, name: &str) -> bool {
228 if let Some(position) = self.presets.get(name) {
229 self.current_position = Some(position.clone());
230 true
231 } else {
232 false
233 }
234 }
235
236 pub fn add_preset(&mut self, name: &str, position: GeolocationPosition) {
238 let _ = self.presets.insert(name.to_string(), position);
239 }
240
241 pub fn get_current_position(&self) -> Result<GeolocationPosition, GeolocationError> {
245 if let Some(ref error) = self.error_mode {
247 return Err(error.clone());
248 }
249
250 if !self.enabled {
252 return Err(GeolocationError::PositionUnavailable);
253 }
254
255 if !self.permission_granted {
257 return Err(GeolocationError::PermissionDenied);
258 }
259
260 self.current_position
262 .clone()
263 .ok_or(GeolocationError::PositionUnavailable)
264 }
265
266 pub fn set_enabled(&mut self, enabled: bool) {
268 self.enabled = enabled;
269 }
270
271 #[must_use]
273 pub fn is_enabled(&self) -> bool {
274 self.enabled
275 }
276
277 pub fn set_permission(&mut self, granted: bool) {
279 self.permission_granted = granted;
280 }
281
282 #[must_use]
284 pub fn is_permission_granted(&self) -> bool {
285 self.permission_granted
286 }
287
288 pub fn simulate_error(&mut self, error: GeolocationError) {
290 self.error_mode = Some(error);
291 }
292
293 pub fn clear_error(&mut self) {
295 self.error_mode = None;
296 }
297
298 #[must_use]
300 pub fn list_presets(&self) -> Vec<&str> {
301 self.presets.keys().map(String::as_str).collect()
302 }
303
304 #[must_use]
306 pub fn get_preset(&self, name: &str) -> Option<&GeolocationPosition> {
307 self.presets.get(name)
308 }
309
310 pub fn clear_position(&mut self) {
312 self.current_position = None;
313 }
314
315 pub fn reset(&mut self) {
317 self.current_position = None;
318 self.enabled = true;
319 self.permission_granted = true;
320 self.error_mode = None;
321 }
322}
323
324#[cfg(test)]
325#[allow(clippy::unwrap_used, clippy::expect_used)]
326mod tests {
327 use super::*;
328
329 #[test]
332 fn test_position_new() {
333 let pos = GeolocationPosition::new(40.7128, -74.0060, 5.0);
334 assert!((pos.latitude - 40.7128).abs() < 0.0001);
335 assert!((pos.longitude - (-74.0060)).abs() < 0.0001);
336 assert!((pos.accuracy - 5.0).abs() < 0.0001);
337 assert!(pos.altitude.is_none());
338 assert!(pos.heading.is_none());
339 assert!(pos.speed.is_none());
340 }
341
342 #[test]
343 #[should_panic(expected = "Latitude must be between -90 and 90 degrees")]
344 fn test_position_invalid_latitude_high() {
345 let _ = GeolocationPosition::new(91.0, 0.0, 10.0);
346 }
347
348 #[test]
349 #[should_panic(expected = "Latitude must be between -90 and 90 degrees")]
350 fn test_position_invalid_latitude_low() {
351 let _ = GeolocationPosition::new(-91.0, 0.0, 10.0);
352 }
353
354 #[test]
355 #[should_panic(expected = "Longitude must be between -180 and 180 degrees")]
356 fn test_position_invalid_longitude_high() {
357 let _ = GeolocationPosition::new(0.0, 181.0, 10.0);
358 }
359
360 #[test]
361 #[should_panic(expected = "Longitude must be between -180 and 180 degrees")]
362 fn test_position_invalid_longitude_low() {
363 let _ = GeolocationPosition::new(0.0, -181.0, 10.0);
364 }
365
366 #[test]
367 #[should_panic(expected = "Accuracy must be non-negative")]
368 fn test_position_invalid_accuracy() {
369 let _ = GeolocationPosition::new(0.0, 0.0, -1.0);
370 }
371
372 #[test]
373 fn test_position_with_altitude() {
374 let pos = GeolocationPosition::new(0.0, 0.0, 10.0).with_altitude(100.0, 5.0);
375 assert_eq!(pos.altitude, Some(100.0));
376 assert_eq!(pos.altitude_accuracy, Some(5.0));
377 }
378
379 #[test]
380 fn test_position_with_heading() {
381 let pos = GeolocationPosition::new(0.0, 0.0, 10.0).with_heading(90.0);
382 assert_eq!(pos.heading, Some(90.0));
383 }
384
385 #[test]
386 #[should_panic(expected = "Heading must be between 0 and 360 degrees")]
387 fn test_position_invalid_heading() {
388 let _ = GeolocationPosition::new(0.0, 0.0, 10.0).with_heading(361.0);
389 }
390
391 #[test]
392 fn test_position_with_speed() {
393 let pos = GeolocationPosition::new(0.0, 0.0, 10.0).with_speed(10.0);
394 assert_eq!(pos.speed, Some(10.0));
395 }
396
397 #[test]
398 #[should_panic(expected = "Speed must be non-negative")]
399 fn test_position_invalid_speed() {
400 let _ = GeolocationPosition::new(0.0, 0.0, 10.0).with_speed(-1.0);
401 }
402
403 #[test]
404 fn test_position_builder_chain() {
405 let pos = GeolocationPosition::new(40.7128, -74.0060, 5.0)
406 .with_altitude(10.0, 2.0)
407 .with_heading(45.0)
408 .with_speed(5.0);
409
410 assert!((pos.latitude - 40.7128).abs() < 0.0001);
411 assert_eq!(pos.altitude, Some(10.0));
412 assert_eq!(pos.heading, Some(45.0));
413 assert_eq!(pos.speed, Some(5.0));
414 }
415
416 #[test]
419 fn test_preset_new_york() {
420 let pos = GeolocationPosition::new_york();
421 assert!((pos.latitude - 40.758896).abs() < 0.0001);
422 assert!((pos.longitude - (-73.985130)).abs() < 0.0001);
423 }
424
425 #[test]
426 fn test_preset_tokyo() {
427 let pos = GeolocationPosition::tokyo();
428 assert!((pos.latitude - 35.659492).abs() < 0.0001);
429 assert!((pos.longitude - 139.700472).abs() < 0.0001);
430 }
431
432 #[test]
433 fn test_preset_london() {
434 let pos = GeolocationPosition::london();
435 assert!((pos.latitude - 51.508039).abs() < 0.0001);
436 assert!((pos.longitude - (-0.128069)).abs() < 0.0001);
437 }
438
439 #[test]
440 fn test_preset_paris() {
441 let pos = GeolocationPosition::paris();
442 assert!((pos.latitude - 48.858370).abs() < 0.0001);
443 assert!((pos.longitude - 2.294481).abs() < 0.0001);
444 }
445
446 #[test]
447 fn test_preset_sydney() {
448 let pos = GeolocationPosition::sydney();
449 assert!(pos.latitude < 0.0); assert!(pos.longitude > 0.0);
451 }
452
453 #[test]
454 fn test_preset_san_francisco() {
455 let pos = GeolocationPosition::san_francisco();
456 assert!((pos.latitude - 37.820587).abs() < 0.0001);
457 assert!((pos.longitude - (-122.478264)).abs() < 0.0001);
458 }
459
460 #[test]
461 fn test_preset_berlin() {
462 let pos = GeolocationPosition::berlin();
463 assert!((pos.latitude - 52.516275).abs() < 0.0001);
464 assert!((pos.longitude - 13.377704).abs() < 0.0001);
465 }
466
467 #[test]
468 fn test_preset_singapore() {
469 let pos = GeolocationPosition::singapore();
470 assert!(pos.latitude > 0.0 && pos.latitude < 2.0); assert!(pos.longitude > 100.0);
472 }
473
474 #[test]
475 fn test_preset_dubai() {
476 let pos = GeolocationPosition::dubai();
477 assert!((pos.latitude - 25.197197).abs() < 0.0001);
478 assert!((pos.longitude - 55.274376).abs() < 0.0001);
479 }
480
481 #[test]
482 fn test_preset_sao_paulo() {
483 let pos = GeolocationPosition::sao_paulo();
484 assert!(pos.latitude < 0.0); assert!(pos.longitude < 0.0); }
487
488 #[test]
491 fn test_mock_new() {
492 let mock = GeolocationMock::new();
493 assert!(mock.is_enabled());
494 assert!(mock.is_permission_granted());
495 assert!(mock.get_current_position().is_err());
496 }
497
498 #[test]
499 fn test_mock_default() {
500 let mock = GeolocationMock::default();
501 assert!(mock.is_enabled());
502 }
503
504 #[test]
505 fn test_mock_set_position() {
506 let mut mock = GeolocationMock::new();
507 let pos = GeolocationPosition::new(40.0, -74.0, 10.0);
508 mock.set_position(pos.clone());
509
510 let result = mock.get_current_position().unwrap();
511 assert_eq!(result, pos);
512 }
513
514 #[test]
515 fn test_mock_set_preset() {
516 let mut mock = GeolocationMock::new();
517 assert!(mock.set_preset("new_york"));
518
519 let pos = mock.get_current_position().unwrap();
520 assert!((pos.latitude - 40.758896).abs() < 0.0001);
521 }
522
523 #[test]
524 fn test_mock_set_preset_unknown() {
525 let mut mock = GeolocationMock::new();
526 assert!(!mock.set_preset("unknown_city"));
527 }
528
529 #[test]
530 fn test_mock_add_custom_preset() {
531 let mut mock = GeolocationMock::new();
532 let pos = GeolocationPosition::new(12.0, 34.0, 5.0);
533 mock.add_preset("custom", pos.clone());
534
535 assert!(mock.set_preset("custom"));
536 let result = mock.get_current_position().unwrap();
537 assert_eq!(result, pos);
538 }
539
540 #[test]
541 fn test_mock_list_presets() {
542 let mock = GeolocationMock::new();
543 let presets = mock.list_presets();
544 assert!(presets.contains(&"new_york"));
545 assert!(presets.contains(&"tokyo"));
546 assert!(presets.contains(&"london"));
547 assert!(presets.len() >= 10);
548 }
549
550 #[test]
551 fn test_mock_get_preset() {
552 let mock = GeolocationMock::new();
553 let pos = mock.get_preset("tokyo");
554 assert!(pos.is_some());
555
556 let unknown = mock.get_preset("unknown");
557 assert!(unknown.is_none());
558 }
559
560 #[test]
561 fn test_mock_permission_denied() {
562 let mut mock = GeolocationMock::new();
563 mock.set_position(GeolocationPosition::new_york());
564 mock.set_permission(false);
565
566 let result = mock.get_current_position();
567 assert_eq!(result, Err(GeolocationError::PermissionDenied));
568 }
569
570 #[test]
571 fn test_mock_disabled() {
572 let mut mock = GeolocationMock::new();
573 mock.set_position(GeolocationPosition::new_york());
574 mock.set_enabled(false);
575
576 let result = mock.get_current_position();
577 assert_eq!(result, Err(GeolocationError::PositionUnavailable));
578 }
579
580 #[test]
581 fn test_mock_simulate_error() {
582 let mut mock = GeolocationMock::new();
583 mock.set_position(GeolocationPosition::new_york());
584 mock.simulate_error(GeolocationError::Timeout);
585
586 let result = mock.get_current_position();
587 assert_eq!(result, Err(GeolocationError::Timeout));
588 }
589
590 #[test]
591 fn test_mock_clear_error() {
592 let mut mock = GeolocationMock::new();
593 mock.set_position(GeolocationPosition::new_york());
594 mock.simulate_error(GeolocationError::Timeout);
595 mock.clear_error();
596
597 assert!(mock.get_current_position().is_ok());
598 }
599
600 #[test]
601 fn test_mock_clear_position() {
602 let mut mock = GeolocationMock::new();
603 mock.set_position(GeolocationPosition::new_york());
604 mock.clear_position();
605
606 assert!(mock.get_current_position().is_err());
607 }
608
609 #[test]
610 fn test_mock_reset() {
611 let mut mock = GeolocationMock::new();
612 mock.set_position(GeolocationPosition::new_york());
613 mock.set_permission(false);
614 mock.set_enabled(false);
615 mock.simulate_error(GeolocationError::Timeout);
616
617 mock.reset();
618
619 assert!(mock.is_enabled());
620 assert!(mock.is_permission_granted());
621 assert!(mock.get_current_position().is_err()); }
623
624 #[test]
625 fn test_error_priority() {
626 let mut mock = GeolocationMock::new();
628 mock.set_position(GeolocationPosition::new_york());
629 mock.set_permission(true);
630 mock.set_enabled(true);
631 mock.simulate_error(GeolocationError::Timeout);
632
633 assert_eq!(mock.get_current_position(), Err(GeolocationError::Timeout));
634 }
635
636 #[test]
637 fn test_position_equality() {
638 let pos1 = GeolocationPosition::new(40.0, -74.0, 10.0);
639 let pos2 = GeolocationPosition::new(40.0, -74.0, 10.0);
640 let pos3 = GeolocationPosition::new(40.0, -74.0, 15.0);
641
642 assert_eq!(pos1, pos2);
643 assert_ne!(pos1, pos3);
644 }
645
646 #[test]
647 fn test_error_equality() {
648 assert_eq!(
649 GeolocationError::PermissionDenied,
650 GeolocationError::PermissionDenied
651 );
652 assert_ne!(
653 GeolocationError::PermissionDenied,
654 GeolocationError::Timeout
655 );
656 }
657
658 #[test]
659 fn test_mock_clone() {
660 let mut mock = GeolocationMock::new();
661 mock.set_position(GeolocationPosition::new_york());
662
663 let cloned = mock.clone();
664 assert!(cloned.get_current_position().is_ok());
665 }
666
667 #[test]
668 fn test_position_clone() {
669 let pos = GeolocationPosition::new_york()
670 .with_altitude(100.0, 5.0)
671 .with_heading(90.0)
672 .with_speed(10.0);
673
674 let cloned = pos.clone();
675 assert_eq!(pos, cloned);
676 }
677
678 mod h0_position_tests {
683 use super::*;
684
685 #[test]
686 fn h0_geo_01_position_new() {
687 let pos = GeolocationPosition::new(45.0, -90.0, 10.0);
688 assert!((pos.latitude - 45.0).abs() < 0.001);
689 assert!((pos.longitude - (-90.0)).abs() < 0.001);
690 }
691
692 #[test]
693 fn h0_geo_02_position_accuracy() {
694 let pos = GeolocationPosition::new(0.0, 0.0, 25.0);
695 assert!((pos.accuracy - 25.0).abs() < 0.001);
696 }
697
698 #[test]
699 fn h0_geo_03_position_no_altitude() {
700 let pos = GeolocationPosition::new(0.0, 0.0, 10.0);
701 assert!(pos.altitude.is_none());
702 }
703
704 #[test]
705 fn h0_geo_04_position_with_altitude() {
706 let pos = GeolocationPosition::new(0.0, 0.0, 10.0).with_altitude(500.0, 10.0);
707 assert_eq!(pos.altitude, Some(500.0));
708 assert_eq!(pos.altitude_accuracy, Some(10.0));
709 }
710
711 #[test]
712 fn h0_geo_05_position_no_heading() {
713 let pos = GeolocationPosition::new(0.0, 0.0, 10.0);
714 assert!(pos.heading.is_none());
715 }
716
717 #[test]
718 fn h0_geo_06_position_with_heading() {
719 let pos = GeolocationPosition::new(0.0, 0.0, 10.0).with_heading(180.0);
720 assert_eq!(pos.heading, Some(180.0));
721 }
722
723 #[test]
724 fn h0_geo_07_position_no_speed() {
725 let pos = GeolocationPosition::new(0.0, 0.0, 10.0);
726 assert!(pos.speed.is_none());
727 }
728
729 #[test]
730 fn h0_geo_08_position_with_speed() {
731 let pos = GeolocationPosition::new(0.0, 0.0, 10.0).with_speed(15.0);
732 assert_eq!(pos.speed, Some(15.0));
733 }
734
735 #[test]
736 fn h0_geo_09_position_boundary_latitude_max() {
737 let pos = GeolocationPosition::new(90.0, 0.0, 10.0);
738 assert!((pos.latitude - 90.0).abs() < 0.001);
739 }
740
741 #[test]
742 fn h0_geo_10_position_boundary_latitude_min() {
743 let pos = GeolocationPosition::new(-90.0, 0.0, 10.0);
744 assert!((pos.latitude - (-90.0)).abs() < 0.001);
745 }
746 }
747
748 mod h0_preset_location_tests {
749 use super::*;
750
751 #[test]
752 fn h0_geo_11_new_york_northern_hemisphere() {
753 let pos = GeolocationPosition::new_york();
754 assert!(pos.latitude > 0.0);
755 }
756
757 #[test]
758 fn h0_geo_12_new_york_western_hemisphere() {
759 let pos = GeolocationPosition::new_york();
760 assert!(pos.longitude < 0.0);
761 }
762
763 #[test]
764 fn h0_geo_13_tokyo_eastern_hemisphere() {
765 let pos = GeolocationPosition::tokyo();
766 assert!(pos.longitude > 0.0);
767 }
768
769 #[test]
770 fn h0_geo_14_london_near_prime_meridian() {
771 let pos = GeolocationPosition::london();
772 assert!(pos.longitude.abs() < 1.0);
773 }
774
775 #[test]
776 fn h0_geo_15_paris_europe() {
777 let pos = GeolocationPosition::paris();
778 assert!(pos.latitude > 45.0 && pos.latitude < 50.0);
779 }
780
781 #[test]
782 fn h0_geo_16_sydney_southern_hemisphere() {
783 let pos = GeolocationPosition::sydney();
784 assert!(pos.latitude < 0.0);
785 }
786
787 #[test]
788 fn h0_geo_17_san_francisco_west_coast() {
789 let pos = GeolocationPosition::san_francisco();
790 assert!(pos.longitude < -120.0);
791 }
792
793 #[test]
794 fn h0_geo_18_berlin_central_europe() {
795 let pos = GeolocationPosition::berlin();
796 assert!(pos.longitude > 10.0 && pos.longitude < 15.0);
797 }
798
799 #[test]
800 fn h0_geo_19_singapore_near_equator() {
801 let pos = GeolocationPosition::singapore();
802 assert!(pos.latitude.abs() < 5.0);
803 }
804
805 #[test]
806 fn h0_geo_20_sao_paulo_south_america() {
807 let pos = GeolocationPosition::sao_paulo();
808 assert!(pos.latitude < 0.0);
809 assert!(pos.longitude < 0.0);
810 }
811 }
812
813 mod h0_mock_tests {
814 use super::*;
815
816 #[test]
817 fn h0_geo_21_mock_new_enabled() {
818 let mock = GeolocationMock::new();
819 assert!(mock.is_enabled());
820 }
821
822 #[test]
823 fn h0_geo_22_mock_new_permission_granted() {
824 let mock = GeolocationMock::new();
825 assert!(mock.is_permission_granted());
826 }
827
828 #[test]
829 fn h0_geo_23_mock_default() {
830 let mock = GeolocationMock::default();
831 assert!(mock.is_enabled());
832 }
833
834 #[test]
835 fn h0_geo_24_mock_no_initial_position() {
836 let mock = GeolocationMock::new();
837 assert!(mock.get_current_position().is_err());
838 }
839
840 #[test]
841 fn h0_geo_25_mock_set_position() {
842 let mut mock = GeolocationMock::new();
843 mock.set_position(GeolocationPosition::new_york());
844 assert!(mock.get_current_position().is_ok());
845 }
846
847 #[test]
848 fn h0_geo_26_mock_set_preset_valid() {
849 let mut mock = GeolocationMock::new();
850 assert!(mock.set_preset("tokyo"));
851 }
852
853 #[test]
854 fn h0_geo_27_mock_set_preset_invalid() {
855 let mut mock = GeolocationMock::new();
856 assert!(!mock.set_preset("invalid_city"));
857 }
858
859 #[test]
860 fn h0_geo_28_mock_add_custom_preset() {
861 let mut mock = GeolocationMock::new();
862 mock.add_preset("custom", GeolocationPosition::new(10.0, 20.0, 5.0));
863 assert!(mock.set_preset("custom"));
864 }
865
866 #[test]
867 fn h0_geo_29_mock_list_presets() {
868 let mock = GeolocationMock::new();
869 let presets = mock.list_presets();
870 assert!(presets.len() >= 10);
871 }
872
873 #[test]
874 fn h0_geo_30_mock_get_preset() {
875 let mock = GeolocationMock::new();
876 assert!(mock.get_preset("london").is_some());
877 }
878 }
879
880 mod h0_mock_state_tests {
881 use super::*;
882
883 #[test]
884 fn h0_geo_31_mock_set_enabled() {
885 let mut mock = GeolocationMock::new();
886 mock.set_enabled(false);
887 assert!(!mock.is_enabled());
888 }
889
890 #[test]
891 fn h0_geo_32_mock_set_permission() {
892 let mut mock = GeolocationMock::new();
893 mock.set_permission(false);
894 assert!(!mock.is_permission_granted());
895 }
896
897 #[test]
898 fn h0_geo_33_mock_clear_position() {
899 let mut mock = GeolocationMock::new();
900 mock.set_position(GeolocationPosition::new_york());
901 mock.clear_position();
902 assert!(mock.get_current_position().is_err());
903 }
904
905 #[test]
906 fn h0_geo_34_mock_reset() {
907 let mut mock = GeolocationMock::new();
908 mock.set_enabled(false);
909 mock.set_permission(false);
910 mock.reset();
911 assert!(mock.is_enabled());
912 assert!(mock.is_permission_granted());
913 }
914
915 #[test]
916 fn h0_geo_35_mock_clone() {
917 let mut mock = GeolocationMock::new();
918 mock.set_position(GeolocationPosition::new_york());
919 let cloned = mock.clone();
920 assert!(cloned.get_current_position().is_ok());
921 }
922 }
923
924 mod h0_error_tests {
925 use super::*;
926
927 #[test]
928 fn h0_geo_36_error_permission_denied() {
929 let mut mock = GeolocationMock::new();
930 mock.set_position(GeolocationPosition::new_york());
931 mock.set_permission(false);
932 assert_eq!(
933 mock.get_current_position(),
934 Err(GeolocationError::PermissionDenied)
935 );
936 }
937
938 #[test]
939 fn h0_geo_37_error_position_unavailable() {
940 let mut mock = GeolocationMock::new();
941 mock.set_position(GeolocationPosition::new_york());
942 mock.set_enabled(false);
943 assert_eq!(
944 mock.get_current_position(),
945 Err(GeolocationError::PositionUnavailable)
946 );
947 }
948
949 #[test]
950 fn h0_geo_38_error_timeout_simulated() {
951 let mut mock = GeolocationMock::new();
952 mock.set_position(GeolocationPosition::new_york());
953 mock.simulate_error(GeolocationError::Timeout);
954 assert_eq!(mock.get_current_position(), Err(GeolocationError::Timeout));
955 }
956
957 #[test]
958 fn h0_geo_39_error_clear() {
959 let mut mock = GeolocationMock::new();
960 mock.set_position(GeolocationPosition::new_york());
961 mock.simulate_error(GeolocationError::Timeout);
962 mock.clear_error();
963 assert!(mock.get_current_position().is_ok());
964 }
965
966 #[test]
967 fn h0_geo_40_error_priority_over_state() {
968 let mut mock = GeolocationMock::new();
969 mock.set_position(GeolocationPosition::new_york());
970 mock.simulate_error(GeolocationError::Timeout);
971 assert_eq!(mock.get_current_position(), Err(GeolocationError::Timeout));
973 }
974 }
975
976 mod h0_position_equality_tests {
977 use super::*;
978
979 #[test]
980 fn h0_geo_41_position_equal() {
981 let p1 = GeolocationPosition::new(40.0, -74.0, 10.0);
982 let p2 = GeolocationPosition::new(40.0, -74.0, 10.0);
983 assert_eq!(p1, p2);
984 }
985
986 #[test]
987 fn h0_geo_42_position_not_equal_latitude() {
988 let p1 = GeolocationPosition::new(40.0, -74.0, 10.0);
989 let p2 = GeolocationPosition::new(41.0, -74.0, 10.0);
990 assert_ne!(p1, p2);
991 }
992
993 #[test]
994 fn h0_geo_43_position_not_equal_longitude() {
995 let p1 = GeolocationPosition::new(40.0, -74.0, 10.0);
996 let p2 = GeolocationPosition::new(40.0, -75.0, 10.0);
997 assert_ne!(p1, p2);
998 }
999
1000 #[test]
1001 fn h0_geo_44_error_equal() {
1002 assert_eq!(
1003 GeolocationError::PermissionDenied,
1004 GeolocationError::PermissionDenied
1005 );
1006 }
1007
1008 #[test]
1009 fn h0_geo_45_error_not_equal() {
1010 assert_ne!(
1011 GeolocationError::PermissionDenied,
1012 GeolocationError::Timeout
1013 );
1014 }
1015 }
1016
1017 mod h0_dubai_preset_tests {
1018 use super::*;
1019
1020 #[test]
1021 fn h0_geo_46_dubai_latitude() {
1022 let pos = GeolocationPosition::dubai();
1023 assert!(pos.latitude > 20.0 && pos.latitude < 30.0);
1024 }
1025
1026 #[test]
1027 fn h0_geo_47_dubai_longitude() {
1028 let pos = GeolocationPosition::dubai();
1029 assert!(pos.longitude > 50.0 && pos.longitude < 60.0);
1030 }
1031
1032 #[test]
1033 fn h0_geo_48_preset_accuracy() {
1034 let pos = GeolocationPosition::new_york();
1035 assert!((pos.accuracy - 10.0).abs() < 0.001);
1036 }
1037
1038 #[test]
1039 fn h0_geo_49_position_builder_complete() {
1040 let pos = GeolocationPosition::new(45.0, -90.0, 5.0)
1041 .with_altitude(100.0, 2.0)
1042 .with_heading(45.0)
1043 .with_speed(10.0);
1044 assert!(pos.altitude.is_some());
1045 assert!(pos.heading.is_some());
1046 assert!(pos.speed.is_some());
1047 }
1048
1049 #[test]
1050 fn h0_geo_50_boundary_longitude() {
1051 let pos1 = GeolocationPosition::new(0.0, 180.0, 10.0);
1052 let pos2 = GeolocationPosition::new(0.0, -180.0, 10.0);
1053 assert!((pos1.longitude - 180.0).abs() < 0.001);
1054 assert!((pos2.longitude - (-180.0)).abs() < 0.001);
1055 }
1056 }
1057}