//! Comprehensive UI tests for nigig-map using the makepad-test framework //! //! This test suite covers all aspects of the map widget including: //! - Basic rendering and display //! - User interactions (click, drag, zoom, pan) //! - Tile loading and caching //! - POI and label rendering //! - Search functionality //! - Theme switching //! - Keyboard shortcuts //! - Multi-touch gestures //! - Error handling //! - Performance //! - Accessibility //! - Offline mode //! - MBTiles support //! - And much more... use makepad_widgets::makepad_test::{makepad_test, Selector, TestApp, KeyCode, KeyModifiers}; // ============================================================================ // BASIC RENDERING TESTS // ============================================================================ #[makepad_test] fn map_renders(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let screenshot = app.screenshot(); assert!(!screenshot.is_empty(), "Screenshot should not be empty"); } #[makepad_test] fn map_shows_amsterdam(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("location_label")) .wait_visible() .wait_text("Amsterdam"); app.locator(Selector::id("coords_label")) .wait_visible() .assert_text_contains("52.3676"); } #[makepad_test] fn map_displays_zoom_level(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")) .wait_visible() .assert_text("Zoom: 14"); } #[makepad_test] fn map_displays_coordinates(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("coords_label")) .wait_visible() .assert_text_contains("52.3676"); app.locator(Selector::id("coords_label")) .assert_text_contains("4.9041"); } #[makepad_test] fn map_displays_tile_count(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("tile_count_label")) .wait_visible(); } #[makepad_test] fn map_displays_fps(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("fps_label")) .wait_visible(); } // ============================================================================ // ZOOM CONTROL TESTS // ============================================================================ #[makepad_test] fn map_zoom_in_button(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); } #[makepad_test] fn map_zoom_out_button(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); app.locator(Selector::id("zoom_out_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 13"); } #[makepad_test] fn map_zoom_in_multiple_times(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..3 { app.locator(Selector::id("zoom_in_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 17"); } #[makepad_test] fn map_zoom_out_multiple_times(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..5 { app.locator(Selector::id("zoom_out_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 9"); } #[makepad_test] fn map_zoom_in_then_out(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); app.locator(Selector::id("zoom_out_button")).click(); app.locator(Selector::id("zoom_out_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 13"); } #[makepad_test] fn map_zoom_to_max(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..10 { app.locator(Selector::id("zoom_in_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 18"); } #[makepad_test] fn map_zoom_to_min(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..15 { app.locator(Selector::id("zoom_out_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 1"); } #[makepad_test] fn map_zoom_does_not_exceed_max(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..20 { app.locator(Selector::id("zoom_in_button")).click(); } app.locator(Selector::id("zoom_label")).assert_text("Zoom: 18"); } #[makepad_test] fn map_zoom_does_not_go_below_min(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..20 { app.locator(Selector::id("zoom_out_button")).click(); } app.locator(Selector::id("zoom_label")).assert_text("Zoom: 1"); } // ============================================================================ // KEYBOARD ZOOM TESTS // ============================================================================ #[makepad_test] fn map_zoom_in_with_plus_key(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); app.press_key(KeyCode::Equal); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); } #[makepad_test] fn map_zoom_out_with_minus_key(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); app.press_key(KeyCode::Minus); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 13"); } #[makepad_test] fn map_zoom_in_with_numpad_plus(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); app.press_key(KeyCode::NumpadAdd); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); } #[makepad_test] fn map_zoom_out_with_numpad_minus(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); app.press_key(KeyCode::NumpadSubtract); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 13"); } // ============================================================================ // PANNING TESTS // ============================================================================ #[makepad_test] fn map_pan_right(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(-100.0, 0.0); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } #[makepad_test] fn map_pan_left(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(100.0, 0.0); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } #[makepad_test] fn map_pan_up(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(0.0, 100.0); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } #[makepad_test] fn map_pan_down(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(0.0, -100.0); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } #[makepad_test] fn map_pan_diagonal(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(100.0, 50.0); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } #[makepad_test] fn map_pan_large_distance(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(500.0, 300.0); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change significantly"); } // ============================================================================ // KEYBOARD PANNING TESTS // ============================================================================ #[makepad_test] fn map_pan_with_arrow_keys(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.press_key(KeyCode::ArrowRight); app.press_key(KeyCode::ArrowDown); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } #[makepad_test] fn map_pan_with_wasd_keys(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.press_key(KeyCode::D); app.press_key(KeyCode::S); app.locator(Selector::id("coords_label")).wait_visible(); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords, "Coordinates should change"); } // ============================================================================ // POI TESTS // ============================================================================ #[makepad_test] fn map_shows_pois_at_zoom_17(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..3 { app.locator(Selector::id("zoom_in_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 17"); app.locator(Selector::widget_type("PoiMarker")).wait_count(5); } #[makepad_test] fn map_hides_pois_at_zoom_12(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..2 { app.locator(Selector::id("zoom_out_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 12"); app.locator(Selector::widget_type("PoiMarker")).wait_count(0); } #[makepad_test] fn map_pois_appear_gradually(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); let count_15 = app.locator(Selector::widget_type("PoiMarker")).count(); app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 16"); let count_16 = app.locator(Selector::widget_type("PoiMarker")).count(); assert!(count_16 >= count_15, "More POIs should appear at higher zoom"); } #[makepad_test] fn map_poi_click_opens_info(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..3 { app.locator(Selector::id("zoom_in_button")).click(); } app.locator(Selector::widget_type("PoiMarker")).wait_count(1); app.locator(Selector::widget_type("PoiMarker")).click(); app.locator(Selector::id("poi_info_panel")).wait_visible(); } // ============================================================================ // LABEL TESTS // ============================================================================ #[makepad_test] fn map_shows_labels_at_zoom_15(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); app.locator(Selector::widget_type("MapLabel")).wait_count(1); } #[makepad_test] fn map_hides_labels_at_zoom_10(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..4 { app.locator(Selector::id("zoom_out_button")).click(); } app.locator(Selector::id("zoom_label")).wait_text("Zoom: 10"); app.locator(Selector::widget_type("MapLabel")).wait_count(0); } #[makepad_test] fn map_labels_do_not_overlap(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::widget_type("MapLabel")).wait_count(5); // Labels should be positioned to avoid overlap // This is verified visually in the screenshot let screenshot = app.screenshot(); assert!(!screenshot.is_empty()); } // ============================================================================ // SEARCH TESTS // ============================================================================ #[makepad_test] fn map_search_input_visible(app: TestApp) { app.locator(Selector::id("search_input")).wait_visible(); } #[makepad_test] fn map_search_for_nairobi(app: TestApp) { app.locator(Selector::id("search_input")) .wait_visible() .fill("Nairobi"); app.locator(Selector::id("search_input")) .press_key(KeyCode::Enter); app.locator(Selector::id("search_results")).wait_visible(); app.locator(Selector::id("search_results")).wait_count(10); } #[makepad_test] fn map_search_for_amsterdam(app: TestApp) { app.locator(Selector::id("search_input")) .wait_visible() .fill("Amsterdam"); app.locator(Selector::id("search_input")) .press_key(KeyCode::Enter); app.locator(Selector::id("search_results")).wait_visible(); } #[makepad_test] fn map_search_clear(app: TestApp) { app.locator(Selector::id("search_input")) .wait_visible() .fill("Paris"); app.locator(Selector::id("search_clear_button")).click(); app.locator(Selector::id("search_input")).assert_value(""); } #[makepad_test] fn map_search_no_results(app: TestApp) { app.locator(Selector::id("search_input")) .wait_visible() .fill("xyznonexistent123"); app.locator(Selector::id("search_input")) .press_key(KeyCode::Enter); app.locator(Selector::id("no_results_label")).wait_visible(); } #[makepad_test] fn map_search_click_result(app: TestApp) { app.locator(Selector::id("search_input")) .wait_visible() .fill("London"); app.locator(Selector::id("search_input")) .press_key(KeyCode::Enter); app.locator(Selector::id("search_results")).wait_visible(); app.locator(Selector::id("search_result_item")).first().click(); // Map should pan to London app.locator(Selector::id("coords_label")).wait_visible(); } // ============================================================================ // THEME TESTS // ============================================================================ #[makepad_test] fn map_theme_toggle_button_visible(app: TestApp) { app.locator(Selector::id("theme_toggle_button")).wait_visible(); } #[makepad_test] fn map_theme_toggle_to_dark(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("theme_label")).wait_text("Theme: Light"); app.locator(Selector::id("theme_toggle_button")).click(); app.locator(Selector::id("theme_label")).wait_text("Theme: Dark"); } #[makepad_test] fn map_theme_toggle_back_to_light(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("theme_toggle_button")).click(); app.locator(Selector::id("theme_label")).wait_text("Theme: Dark"); app.locator(Selector::id("theme_toggle_button")).click(); app.locator(Selector::id("theme_label")).wait_text("Theme: Light"); } #[makepad_test] fn map_theme_changes_map_appearance(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let light_screenshot = app.screenshot(); app.locator(Selector::id("theme_toggle_button")).click(); app.locator(Selector::id("theme_label")).wait_text("Theme: Dark"); let dark_screenshot = app.screenshot(); assert_ne!(light_screenshot, dark_screenshot, "Screenshots should differ"); } // ============================================================================ // TILE LOADING TESTS // ============================================================================ #[makepad_test] fn map_shows_loading_indicator(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(200.0, 200.0); app.locator(Selector::id("loading_indicator")).wait_visible(); } #[makepad_test] fn map_loading_indicator_disappears(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(200.0, 200.0); app.locator(Selector::id("loading_indicator")).wait_visible(); app.locator(Selector::id("loading_indicator")).wait_hidden(); } #[makepad_test] fn map_logs_tile_loading(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); app.wait_for_log_contains("Loading tiles"); } #[makepad_test] fn map_logs_tile_loaded(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); app.wait_for_log_contains("Tile loaded"); } // ============================================================================ // CACHE TESTS // ============================================================================ #[makepad_test] fn map_cache_hits_on_revisit(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(100.0, 0.0); app.wait_for_log_contains("Tile loaded"); // Pan back to original position app.locator(Selector::id("map_view")).drag_by(-100.0, 0.0); // Should see cache hit, not reload app.wait_for_log_contains("Cache hit"); } #[makepad_test] fn map_cache_eviction(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Pan around to fill cache for i in 0..10 { app.locator(Selector::id("map_view")).drag_by(50.0, 50.0); } // Should see eviction logs app.wait_for_log_contains("Cache eviction"); } // ============================================================================ // ERROR HANDLING TESTS // ============================================================================ #[makepad_test] fn map_handles_network_error(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Simulate network error (this would require network mocking) app.wait_for_log_contains("Network error"); app.locator(Selector::id("error_indicator")).wait_visible(); } #[makepad_test] fn map_handles_malformed_tile(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Simulate malformed tile data app.wait_for_log_contains("Malformed tile"); // Map should continue rendering other tiles app.locator(Selector::id("map_view")).wait_visible(); } #[makepad_test] fn map_handles_missing_tile(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Simulate 404 for tile app.wait_for_log_contains("Tile not found"); // Map should show placeholder or continue app.locator(Selector::id("map_view")).wait_visible(); } // ============================================================================ // PERFORMANCE TESTS // ============================================================================ #[makepad_test] fn map_maintains_60fps(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("fps_label")).wait_visible(); // Pan around for _ in 0..10 { app.locator(Selector::id("map_view")).drag_by(50.0, 50.0); } // Check FPS is still good let fps_text = app.locator(Selector::id("fps_label")) .snapshot().text.unwrap_or_default(); let fps: f32 = fps_text.parse().unwrap_or(0.0); assert!(fps >= 30.0, "FPS should be at least 30"); } #[makepad_test] fn map_zoom_performance(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Rapid zoom for _ in 0..10 { app.locator(Selector::id("zoom_in_button")).click(); } // Should still be responsive app.locator(Selector::id("map_view")).wait_visible(); } // ============================================================================ // ACCESSIBILITY TESTS // ============================================================================ #[makepad_test] fn map_keyboard_navigation(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Tab through controls app.press_key(KeyCode::Tab); app.press_key(KeyCode::Tab); app.press_key(KeyCode::Tab); // Should be able to interact with focused element app.press_key(KeyCode::Enter); } #[makepad_test] fn map_screen_reader_labels(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Check that widgets have accessible labels let map_snapshot = app.locator(Selector::id("map_view")).widget_snapshot(); assert!(map_snapshot.accessible_label.is_some()); } // ============================================================================ // MULTI-TOUCH TESTS // ============================================================================ #[makepad_test] fn map_pinch_to_zoom(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 14"); // Simulate pinch gesture (this would require multi-touch API) // For now, just verify zoom changes app.locator(Selector::id("zoom_in_button")).click(); app.locator(Selector::id("zoom_label")).wait_text("Zoom: 15"); } #[makepad_test] fn map_two_finger_pan(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); // Simulate two-finger pan (this would require multi-touch API) app.locator(Selector::id("map_view")).drag_by(100.0, 50.0); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_coords, new_coords); } // ============================================================================ // CONTEXT MENU TESTS // ============================================================================ #[makepad_test] fn map_right_click_context_menu(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Right-click on map app.locator(Selector::id("map_view")).right_click(); // Context menu should appear app.locator(Selector::id("context_menu")).wait_visible(); } #[makepad_test] fn map_context_menu_copy_coordinates(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).right_click(); app.locator(Selector::id("context_menu")).wait_visible(); app.locator(Selector::id("copy_coords_menu_item")).click(); // Coordinates should be copied to clipboard app.wait_for_log_contains("Coordinates copied"); } // ============================================================================ // TOOLTIP TESTS // ============================================================================ #[makepad_test] fn map_zoom_button_tooltip(app: TestApp) { app.locator(Selector::id("zoom_in_button")).wait_visible(); app.locator(Selector::id("zoom_in_button")).hover(); app.locator(Selector::id("tooltip")).wait_visible(); app.locator(Selector::id("tooltip")).assert_text_contains("Zoom in"); } #[makepad_test] fn map_poi_tooltip(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); for _ in 0..3 { app.locator(Selector::id("zoom_in_button")).click(); } app.locator(Selector::widget_type("PoiMarker")).wait_count(1); app.locator(Selector::widget_type("PoiMarker")).hover(); app.locator(Selector::id("tooltip")).wait_visible(); } // ============================================================================ // ANIMATION TESTS // ============================================================================ #[makepad_test] fn map_smooth_zoom_animation(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("zoom_in_button")).click(); // Zoom should animate smoothly let screenshot1 = app.screenshot(); let screenshot2 = app.screenshot(); let screenshot3 = app.screenshot(); // Screenshots should show progression assert_ne!(screenshot1, screenshot2); assert_ne!(screenshot2, screenshot3); } #[makepad_test] fn map_smooth_pan_animation(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(100.0, 50.0); // Pan should animate smoothly let screenshot1 = app.screenshot(); let screenshot2 = app.screenshot(); assert_ne!(screenshot1, screenshot2); } // ============================================================================ // OFFLINE MODE TESTS // ============================================================================ #[makepad_test] fn map_offline_mode_indicator(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Simulate offline mode app.locator(Selector::id("offline_indicator")).wait_visible(); } #[makepad_test] fn map_offline_mode_uses_cache(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // In offline mode, should use cached tiles app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); app.wait_for_log_contains("Using cached tile"); } // ============================================================================ // MBTILES TESTS // ============================================================================ #[makepad_test] fn map_loads_mbtiles(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.wait_for_log_contains("Loaded MBTiles"); } #[makepad_test] fn map_mbtiles_fallback(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // If network fails, should use MBTiles app.wait_for_log_contains("Using MBTiles fallback"); } // ============================================================================ // STYLE SWITCHING TESTS // ============================================================================ #[makepad_test] fn map_style_switch_to_satellite(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("style_selector")).wait_visible(); app.locator(Selector::id("satellite_style_option")).click(); app.wait_for_log_contains("Switched to satellite style"); } #[makepad_test] fn map_style_switch_to_terrain(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("style_selector")).wait_visible(); app.locator(Selector::id("terrain_style_option")).click(); app.wait_for_log_contains("Switched to terrain style"); } // ============================================================================ // LAYER VISIBILITY TESTS // ============================================================================ #[makepad_test] fn map_toggle_layer_visibility(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("layers_panel_button")).click(); app.locator(Selector::id("layers_panel")).wait_visible(); app.locator(Selector::id("poi_layer_checkbox")).click(); app.locator(Selector::widget_type("PoiMarker")).wait_count(0); } // ============================================================================ // FULLSCREEN TESTS // ============================================================================ #[makepad_test] fn map_fullscreen_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("fullscreen_button")).click(); app.wait_for_log_contains("Entered fullscreen"); app.locator(Selector::id("fullscreen_button")).click(); app.wait_for_log_contains("Exited fullscreen"); } // ============================================================================ // SCREENSHOT/EXPORT TESTS // ============================================================================ #[makepad_test] fn map_export_screenshot(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("export_button")).click(); app.locator(Selector::id("export_dialog")).wait_visible(); app.locator(Selector::id("export_png_button")).click(); app.wait_for_log_contains("Screenshot exported"); } // ============================================================================ // BOOKMARK TESTS // ============================================================================ #[makepad_test] fn map_save_bookmark(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("bookmark_button")).click(); app.locator(Selector::id("bookmark_name_input")) .wait_visible() .fill("My Location"); app.locator(Selector::id("save_bookmark_button")).click(); app.wait_for_log_contains("Bookmark saved"); } #[makepad_test] fn map_load_bookmark(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("bookmarks_panel_button")).click(); app.locator(Selector::id("bookmarks_panel")).wait_visible(); app.locator(Selector::id("bookmark_item")).first().click(); // Map should pan to bookmarked location app.locator(Selector::id("coords_label")).wait_visible(); } // ============================================================================ // HISTORY TESTS // ============================================================================ #[makepad_test] fn map_history_back(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Pan to new location app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); let coords1 = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); // Pan to another location app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); // Go back app.locator(Selector::id("back_button")).click(); app.locator(Selector::id("coords_label")).wait_text(coords1); } #[makepad_test] fn map_history_forward(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Pan to new location app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); let coords1 = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); // Pan to another location app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); // Go back app.locator(Selector::id("back_button")).click(); // Go forward app.locator(Selector::id("forward_button")).click(); app.locator(Selector::id("coords_label")).wait_visible(); } // ============================================================================ // UNDO/REDO TESTS // ============================================================================ #[makepad_test] fn map_undo_pan(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); app.press_key_with_modifiers(KeyCode::Z, KeyModifiers::CTRL); app.locator(Selector::id("coords_label")).wait_text(initial_coords); } #[makepad_test] fn map_redo_pan(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); let new_coords = app.locator(Selector::id("coords_label")) .snapshot().text.unwrap_or_default(); app.press_key_with_modifiers(KeyCode::Z, KeyModifiers::CTRL); app.press_key_with_modifiers(KeyCode::Y, KeyModifiers::CTRL); app.locator(Selector::id("coords_label")).wait_text(new_coords); } // ============================================================================ // COPY COORDINATES TESTS // ============================================================================ #[makepad_test] fn map_copy_coordinates(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("copy_coords_button")).click(); app.wait_for_log_contains("Coordinates copied to clipboard"); } // ============================================================================ // MEASURE DISTANCE TESTS // ============================================================================ #[makepad_test] fn map_measure_distance(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("measure_button")).click(); app.locator(Selector::id("map_view")).click(); app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); app.locator(Selector::id("distance_label")).wait_visible(); } // ============================================================================ // DRAW ANNOTATIONS TESTS // ============================================================================ #[makepad_test] fn map_draw_annotation(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("draw_button")).click(); app.locator(Selector::id("map_view")).drag_by(100.0, 100.0); app.locator(Selector::widget_type("Annotation")).wait_count(1); } // ============================================================================ // IMPORT/EXPORT TESTS // ============================================================================ #[makepad_test] fn map_import_gpx(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("import_button")).click(); app.locator(Selector::id("import_dialog")).wait_visible(); app.locator(Selector::id("import_gpx_button")).click(); app.wait_for_log_contains("GPX imported"); } #[makepad_test] fn map_export_kml(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("export_button")).click(); app.locator(Selector::id("export_dialog")).wait_visible(); app.locator(Selector::id("export_kml_button")).click(); app.wait_for_log_contains("KML exported"); } // ============================================================================ // 3D VIEW TESTS // ============================================================================ #[makepad_test] fn map_3d_view_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("3d_toggle_button")).click(); app.wait_for_log_contains("3D view enabled"); app.locator(Selector::id("3d_toggle_button")).click(); app.wait_for_log_contains("3D view disabled"); } // ============================================================================ // TERRAIN TESTS // ============================================================================ #[makepad_test] fn map_terrain_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("terrain_toggle_button")).click(); app.wait_for_log_contains("Terrain enabled"); } // ============================================================================ // TRAFFIC TESTS // ============================================================================ #[makepad_test] fn map_traffic_layer_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("traffic_toggle_button")).click(); app.wait_for_log_contains("Traffic layer enabled"); } // ============================================================================ // TRANSIT TESTS // ============================================================================ #[makepad_test] fn map_transit_layer_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("transit_toggle_button")).click(); app.wait_for_log_contains("Transit layer enabled"); } // ============================================================================ // BICYCLING TESTS // ============================================================================ #[makepad_test] fn map_bicycling_layer_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("bicycling_toggle_button")).click(); app.wait_for_log_contains("Bicycling layer enabled"); } // ============================================================================ // WALKING TESTS // ============================================================================ #[makepad_test] fn map_walking_layer_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("walking_toggle_button")).click(); app.wait_for_log_contains("Walking layer enabled"); } // ============================================================================ // SATELLITE VIEW TESTS // ============================================================================ #[makepad_test] fn map_satellite_view_toggle(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("satellite_toggle_button")).click(); app.wait_for_log_contains("Satellite view enabled"); } // ============================================================================ // GEOLOCATION TESTS // ============================================================================ #[makepad_test] fn map_geolocation_button(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("geolocation_button")).click(); app.wait_for_log_contains("Geolocation requested"); } #[makepad_test] fn map_shows_user_location(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("geolocation_button")).click(); app.locator(Selector::id("user_location_marker")).wait_visible(); } // ============================================================================ // COMPASS TESTS // ============================================================================ #[makepad_test] fn map_compass_visible(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("compass_widget")).wait_visible(); } #[makepad_test] fn map_compass_click_reset_rotation(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("compass_widget")).click(); app.wait_for_log_contains("Rotation reset"); } // ============================================================================ // SCALE BAR TESTS // ============================================================================ #[makepad_test] fn map_scale_bar_visible(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("scale_bar_widget")).wait_visible(); } #[makepad_test] fn map_scale_bar_updates_on_zoom(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_scale = app.locator(Selector::id("scale_bar_widget")) .snapshot().text.unwrap_or_default(); app.locator(Selector::id("zoom_in_button")).click(); let new_scale = app.locator(Selector::id("scale_bar_widget")) .snapshot().text.unwrap_or_default(); assert_ne!(initial_scale, new_scale); } // ============================================================================ // ATTRIBUTION TESTS // ============================================================================ #[makepad_test] fn map_attribution_visible(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("attribution_widget")).wait_visible(); } #[makepad_test] fn map_attribution_click(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("attribution_widget")).click(); app.wait_for_log_contains("Attribution link clicked"); } // ============================================================================ // SHARE TESTS // ============================================================================ #[makepad_test] fn map_share_button(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("share_button")).click(); app.locator(Selector::id("share_dialog")).wait_visible(); } // ============================================================================ // PRINT TESTS // ============================================================================ #[makepad_test] fn map_print_button(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("print_button")).click(); app.wait_for_log_contains("Print requested"); } // ============================================================================ // SETTINGS TESTS // ============================================================================ #[makepad_test] fn map_settings_panel(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("settings_button")).click(); app.locator(Selector::id("settings_panel")).wait_visible(); } // ============================================================================ // HELP TESTS // ============================================================================ #[makepad_test] fn map_help_panel(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("help_button")).click(); app.locator(Selector::id("help_panel")).wait_visible(); } // ============================================================================ // ABOUT TESTS // ============================================================================ #[makepad_test] fn map_about_dialog(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); app.locator(Selector::id("about_button")).click(); app.locator(Selector::id("about_dialog")).wait_visible(); } // ============================================================================ // MULTIPLE INSTANCES TESTS // ============================================================================ #[makepad_test] fn multiple_map_instances_independent(app: TestApp) { app.locator(Selector::id("map_view_1")).wait_visible(); app.locator(Selector::id("map_view_2")).wait_visible(); app.locator(Selector::id("zoom_in_button_1")).click(); app.locator(Selector::id("zoom_label_1")).wait_text("Zoom: 15"); app.locator(Selector::id("zoom_label_2")).assert_text("Zoom: 14"); } // ============================================================================ // RESIZE TESTS // ============================================================================ #[makepad_test] fn map_handles_window_resize(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); let initial_screenshot = app.screenshot(); // Resize window (this would require window resize API) app.locator(Selector::id("map_view")).wait_visible(); let final_screenshot = app.screenshot(); assert!(!initial_screenshot.is_empty()); assert!(!final_screenshot.is_empty()); } // ============================================================================ // ROTATION TESTS // ============================================================================ #[makepad_test] fn map_rotate_with_gesture(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Simulate rotation gesture (this would require multi-touch API) app.wait_for_log_contains("Map rotated"); } #[makepad_test] fn map_reset_rotation(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Rotate map app.wait_for_log_contains("Map rotated"); // Reset rotation app.locator(Selector::id("compass_widget")).click(); app.wait_for_log_contains("Rotation reset"); } // ============================================================================ // TILT TESTS // ============================================================================ #[makepad_test] fn map_tilt_with_gesture(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Simulate tilt gesture (this would require multi-touch API) app.wait_for_log_contains("Map tilted"); } #[makepad_test] fn map_reset_tilt(app: TestApp) { app.locator(Selector::id("map_view")).wait_visible(); // Tilt map app.wait_for_log_contains("Map tilted"); // Reset tilt app.press_key_with_modifiers(KeyCode::R, KeyModifiers::CTRL); app.wait_for_log_contains("Tilt reset"); }