use makepad_widgets::makepad_test::{makepad_test, Selector, TestApp}; /// Skip tests that require a project to be loaded. fn require_project_loaded() -> bool { std::env::var("NIGIG_TEST_MODE").is_ok() } // ── App launch smoke tests ───────────────────────────────────── #[makepad_test] fn app_launches_successfully(app: TestApp) { app.locator(Selector::widget_type("Window")) .wait_visible(); } #[makepad_test] fn construction_screen_is_visible(app: TestApp) { app.locator(Selector::id("main_adaptive_view")) .wait_visible(); } // ── Workspace overlay tests (requires NIGIG_TEST_MODE) ───────── #[makepad_test] fn workspace_overlay_exists_when_opened(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); } #[makepad_test] fn workspace_title_shows_correct_text(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_title")) .wait_visible() .assert_text("Spreadsheet"); } #[makepad_test] fn workspace_close_button_is_clickable(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_close_btn")) .wait_visible() .click(); app.locator(Selector::id("m_workspace_overlay")) .wait_hidden(); } // ── Spreadsheet workspace tests ──────────────────────────────── #[makepad_test] fn spreadsheet_grid_is_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_ss_grid")) .wait_visible(); } #[makepad_test] fn spreadsheet_formula_bar_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_ss_formula_bar")) .wait_visible(); } #[makepad_test] fn spreadsheet_cell_ref_label_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_ss_cell_ref")) .wait_visible(); } #[makepad_test] fn spreadsheet_sum_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_ss_sum_btn")) .wait_visible(); } #[makepad_test] fn spreadsheet_avg_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_ss_avg_btn")) .wait_visible(); } #[makepad_test] fn spreadsheet_clear_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_ss_clear_btn")) .wait_visible(); } // ── Solar calculator workspace tests ─────────────────────────── #[makepad_test] fn solar_calculator_page_is_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); } #[makepad_test] fn solar_tab_buttons_exist(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("solar_load_tab_btn")) .wait_visible(); app.locator(Selector::id("solar_array_tab_btn")) .wait_visible(); app.locator(Selector::id("solar_battery_tab_btn")) .wait_visible(); app.locator(Selector::id("solar_results_tab_btn")) .wait_visible(); } #[makepad_test] fn solar_load_tab_has_energy_input(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("sc_daily_energy")) .wait_visible(); } #[makepad_test] fn solar_load_tab_has_peak_hours_input(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("sc_peak_sun")) .wait_visible(); } #[makepad_test] fn solar_load_tab_has_peak_load_input(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("sc_peak_load")) .wait_visible(); } #[makepad_test] fn solar_calculate_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("sc_calculate_btn")) .wait_visible(); } #[makepad_test] fn solar_array_tab_panel_dropdown_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("solar_array_tab_btn")) .click(); app.locator(Selector::id("sc_panel_dropdown")) .wait_visible(); } #[makepad_test] fn solar_array_tab_arrays_count_input_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("solar_array_tab_btn")) .click(); app.locator(Selector::id("sc_array_count")) .wait_visible(); } #[makepad_test] fn solar_battery_tab_battery_type_dropdown_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); app.locator(Selector::id("solar_battery_tab_btn")) .click(); app.locator(Selector::id("sc_battery_type")) .wait_visible(); } #[makepad_test] fn solar_tab_switching_works(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("solar_calculator_page")) .wait_visible(); // Start on Load tab app.locator(Selector::id("sc_daily_energy")) .wait_visible(); // Switch to Array tab app.locator(Selector::id("solar_array_tab_btn")) .click(); app.locator(Selector::id("sc_panel_dropdown")) .wait_visible(); // Switch to Battery tab app.locator(Selector::id("solar_battery_tab_btn")) .click(); app.locator(Selector::id("sc_battery_type")) .wait_visible(); // Switch to Results tab app.locator(Selector::id("solar_results_tab_btn")) .click(); app.locator(Selector::id("sc_res_system_val")) .wait_visible(); } // ── PageFlip navigation between workspaces ───────────────────── #[makepad_test] fn page_flip_between_workspaces(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("m_workspace_flip")) .wait_visible(); } // ── Project Management workspace tests ───────────────────────── #[makepad_test] fn pm_page_is_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("project_management_page")) .wait_visible(); } #[makepad_test] fn pm_kpi_header_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("m_workspace_overlay")) .wait_visible(); app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("kpi_header")) .wait_visible(); } #[makepad_test] fn pm_kpi_task_count_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("kpi_tasks")) .wait_visible(); } #[makepad_test] fn pm_kpi_duration_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("kpi_duration")) .wait_visible(); } #[makepad_test] fn pm_kpi_progress_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("kpi_progress")) .wait_visible(); } #[makepad_test] fn pm_toolbar_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("pm_toolbar")) .wait_visible(); } #[makepad_test] fn pm_save_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("save_btn")) .wait_visible(); } #[makepad_test] fn pm_undo_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("undo_button")) .wait_visible(); } #[makepad_test] fn pm_redo_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("redo_button")) .wait_visible(); } #[makepad_test] fn pm_add_task_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("add_task_btn")) .wait_visible(); } #[makepad_test] fn pm_add_milestone_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("add_milestone_btn")) .wait_visible(); } #[makepad_test] fn pm_add_group_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("add_group_btn")) .wait_visible(); } #[makepad_test] fn pm_indent_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("indent_btn")) .wait_visible(); } #[makepad_test] fn pm_outdent_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("outdent_btn")) .wait_visible(); } #[makepad_test] fn pm_delete_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("delete_btn")) .wait_visible(); } #[makepad_test] fn pm_zoom_buttons_exist(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("zoom_in_btn")) .wait_visible(); app.locator(Selector::id("zoom_out_btn")) .wait_visible(); } #[makepad_test] fn pm_today_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("today_btn")) .wait_visible(); } #[makepad_test] fn pm_gantt_chart_is_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("gantt_view")) .wait_visible(); } #[makepad_test] fn pm_set_baseline_button_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("project_management_page")) .wait_visible(); app.locator(Selector::id("set_baseline_btn")) .wait_visible(); } // ── CAD workspace tests ──────────────────────────────────────── #[makepad_test] fn cad_viewport_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); } #[makepad_test] fn cad_tool_overlay_exists(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Tool overlay is drawn by the viewport; check for status label app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_tool_key_switches_tool(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Press L to switch to Line tool app.press_key(makepad_widgets::makepad_test::KeyCode::KeyL); // Status label should update app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_escape_cancels_drawing(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Press L then Escape — should return to Select app.press_key(makepad_widgets::makepad_test::KeyCode::KeyL); app.press_key(makepad_widgets::makepad_test::KeyCode::Escape); app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_toggle_ortho_polar(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // F8 toggles ortho, F9 toggles polar app.press_key(makepad_widgets::makepad_test::KeyCode::F8); app.press_key(makepad_widgets::makepad_test::KeyCode::F9); app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_dde_digit_enters_buffer(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to Line tool, click to start line, type digit app.press_key(makepad_widgets::makepad_test::KeyCode::KeyL); app.locator(Selector::id("cad_viewport")) .click(); // Type a digit — DDE buffer should contain "5" app.press_key(makepad_widgets::makepad_test::KeyCode::Key5); } #[makepad_test] fn cad_dde_backspace_removes_char(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to Line, click, type digits, backspace app.press_key(makepad_widgets::makepad_test::KeyCode::KeyL); app.locator(Selector::id("cad_viewport")) .click(); app.press_key(makepad_widgets::makepad_test::KeyCode::Key5); app.press_key(makepad_widgets::makepad_test::KeyCode::Key3); app.press_key(makepad_widgets::makepad_test::KeyCode::Backspace); } #[makepad_test] fn cad_select_tool_click(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // S should switch to Select tool app.press_key(makepad_widgets::makepad_test::KeyCode::KeyS); app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_multiple_tool_switches(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Cycle through several tools via keyboard let keys = [ makepad_widgets::makepad_test::KeyCode::KeyL, makepad_widgets::makepad_test::KeyCode::KeyR, makepad_widgets::makepad_test::KeyCode::KeyC, makepad_widgets::makepad_test::KeyCode::KeyW, ]; for key in keys { app.press_key(key); app.locator(Selector::id("cad_status_label")) .wait_visible(); } } // ── Section shape tests ──────────────────────────────────────── #[makepad_test] fn cad_beam_tool_shows_rect_section(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Press B to switch to Beam tool app.press_key(makepad_widgets::makepad_test::KeyCode::KeyB); app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_beam_tab_cycles_section(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to Beam tool (B), then Tab to cycle section app.press_key(makepad_widgets::makepad_test::KeyCode::KeyB); app.locator(Selector::id("cad_status_label")) .wait_visible(); app.press_key(makepad_widgets::makepad_test::KeyCode::Tab); app.locator(Selector::id("cad_status_label")) .wait_visible(); app.press_key(makepad_widgets::makepad_test::KeyCode::Tab); app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_beam_section_indicator_drawn(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to Beam, create a beam, then verify section indicator appears app.press_key(makepad_widgets::makepad_test::KeyCode::KeyB); app.locator(Selector::id("cad_viewport")) .click(); app.press_key(makepad_widgets::makepad_test::KeyCode::Escape); // Verify viewport still renders app.locator(Selector::id("cad_viewport")) .wait_visible(); } #[makepad_test] fn cad_beam_ibeam_section_switch(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to Beam tool, Tab once to I-Beam, Tab once to HSS, Tab back to Rect app.press_key(makepad_widgets::makepad_test::KeyCode::KeyB); app.press_key(makepad_widgets::makepad_test::KeyCode::Tab); app.press_key(makepad_widgets::makepad_test::KeyCode::Tab); app.press_key(makepad_widgets::makepad_test::KeyCode::Tab); app.locator(Selector::id("cad_status_label")) .wait_visible(); } #[makepad_test] fn cad_beam_section_ignored_when_not_beam(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to Line tool — Tab should NOT cycle beam section app.press_key(makepad_widgets::makepad_test::KeyCode::KeyL); app.press_key(makepad_widgets::makepad_test::KeyCode::Tab); app.locator(Selector::id("cad_status_label")) .wait_visible(); } // =========================================================================== // Session 6 — Selection actions UI tests // =========================================================================== #[makepad_test] fn cad_escape_deselects(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Press Escape — should deselect all app.press_key(makepad_widgets::makepad_test::KeyCode::Escape); app.locator(Selector::id("cad_viewport")) .wait_visible(); } #[makepad_test] fn cad_isolate_toggle(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Click on viewport to select something, then press I to isolate app.locator(Selector::id("cad_viewport")) .click(); app.press_key(makepad_widgets::makepad_test::KeyCode::KeyI); // Press I again to restore app.press_key(makepad_widgets::makepad_test::KeyCode::KeyI); app.locator(Selector::id("cad_viewport")) .wait_visible(); } #[makepad_test] fn cad_dof_toggle_shift_d(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Select something and toggle DOF app.locator(Selector::id("cad_viewport")) .click(); app.press_key(makepad_widgets::makepad_test::KeyCode::Shift); app.press_key(makepad_widgets::makepad_test::KeyCode::KeyD); app.locator(Selector::id("cad_viewport")) .wait_visible(); } #[makepad_test] fn cad_properties_panel_dof_row(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Select a part to show properties panel app.locator(Selector::id("cad_viewport")) .click(); // Properties panel should now be visible with DOF buttons app.locator(Selector::id("properties_panel_view")) .wait_visible(); } // =========================================================================== // Session 7 — Export + PdfPreview UI tests // =========================================================================== #[makepad_test] fn cad_stl_export_button(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Click STL export button app.locator(Selector::id("export_stl_btn")) .click(); // Status label should update with STL status app.locator(Selector::id("status_label")) .wait_visible(); } #[makepad_test] fn cad_svg_export_button(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Click SVG export button app.locator(Selector::id("export_svg_btn")) .click(); // Should auto-switch to preview tab after export app.locator(Selector::id("status_label")) .wait_visible(); } #[makepad_test] fn cad_pdf_tab_switch(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Click PDF tab to switch to preview page app.locator(Selector::id("desktop_pdf_tab_btn")) .click(); // Preview page should be visible app.locator(Selector::id("desktop_pdf_page")) .wait_visible(); } #[makepad_test] fn cad_pdf_tab_then_script_tab(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to PDF preview app.locator(Selector::id("desktop_pdf_tab_btn")) .click(); app.locator(Selector::id("desktop_pdf_page")) .wait_visible(); // Switch back to Script app.locator(Selector::id("desktop_editor_tab_btn")) .click(); app.locator(Selector::id("desktop_script_page")) .wait_visible(); } #[makepad_test] fn cad_svg_export_shows_preview(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Click SVG export — should show SVG preview and hide placeholder app.locator(Selector::id("export_svg_btn")) .click(); app.locator(Selector::id("desktop_svg_preview")) .wait_visible(); } #[makepad_test] fn cad_preview_placeholder_initially_visible(app: TestApp) { if !require_project_loaded() { return; } app.locator(Selector::id("cad_viewport")) .wait_visible(); // Switch to PDF preview page app.locator(Selector::id("desktop_pdf_tab_btn")) .click(); // Placeholder should be visible initially (no export yet) app.locator(Selector::id("desktop_preview_placeholder")) .wait_visible(); }