From 94c356845e0371b8b41975f4de1223ff079f1aec Mon Sep 17 00:00:00 2001 From: SoftFever Date: Wed, 3 Jun 2026 01:45:46 +0800 Subject: [PATCH] test(automation): MockUiBackend recording test double --- tests/automation/CMakeLists.txt | 1 + tests/automation/MockUiBackend.cpp | 13 +++++++ tests/automation/MockUiBackend.hpp | 59 ++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 tests/automation/MockUiBackend.cpp create mode 100644 tests/automation/MockUiBackend.hpp diff --git a/tests/automation/CMakeLists.txt b/tests/automation/CMakeLists.txt index cd9a3cf041..cf73dd8d4c 100644 --- a/tests/automation/CMakeLists.txt +++ b/tests/automation/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(${_TEST_NAME}_tests automation_tests.cpp test_serializer.cpp test_locator.cpp + MockUiBackend.cpp ${CMAKE_SOURCE_DIR}/src/slic3r/GUI/Automation/WidgetSerializer.cpp ${CMAKE_SOURCE_DIR}/src/slic3r/GUI/Automation/Locator.cpp ) diff --git a/tests/automation/MockUiBackend.cpp b/tests/automation/MockUiBackend.cpp new file mode 100644 index 0000000000..a0ce1cbe00 --- /dev/null +++ b/tests/automation/MockUiBackend.cpp @@ -0,0 +1,13 @@ +#include "MockUiBackend.hpp" +#include + +using namespace Slic3r::GUI::Automation; + +TEST_CASE("MockUiBackend records calls", "[automation][mock]") { + MockUiBackend mock; + UiNode n; n.id = "btn_slice"; + mock.click(n, MouseButton::Left, false, {}); + REQUIRE(mock.clicked_ids.size() == 1); + CHECK(mock.clicked_ids[0] == "btn_slice"); + CHECK(mock.click_buttons[0] == MouseButton::Left); +} diff --git a/tests/automation/MockUiBackend.hpp b/tests/automation/MockUiBackend.hpp new file mode 100644 index 0000000000..b159fa4370 --- /dev/null +++ b/tests/automation/MockUiBackend.hpp @@ -0,0 +1,59 @@ +#pragma once +#include "slic3r/GUI/Automation/IUiBackend.hpp" +#include +#include + +namespace Slic3r { namespace GUI { namespace Automation { + +// Deterministic fake backend for dispatcher tests. Records every primitive call +// and returns canned data. `tree_provider` lets a test return different trees on +// successive dump_tree() calls (used for sync.wait_for tests). +class MockUiBackend : public IUiBackend { +public: + // Recorded calls (inspected by tests). + int refresh_count = 0; + int dump_count = 0; + std::vector clicked_ids; // node.id of each click() + std::vector click_buttons; + std::vector typed_text; + std::vector> sent_keys; + int screenshot_window_count = 0; + int screenshot_viewport_count = 0; + + // Canned outputs (set by tests). + UiNode tree; // default tree for dump_tree + AppState state; + PngImage canned_png{ {0x89,0x50,0x4E,0x47}, 4, 4 }; // fake "PNG" bytes + bool click_result = true; + + // Optional: per-call tree provider (overrides `tree` when set). + std::function tree_provider; + + void refresh_ui() override { ++refresh_count; } + UiNode dump_tree(const DumpOptions&) override { + const int idx = dump_count++; + return tree_provider ? tree_provider(idx) : tree; + } + AppState app_state() override { return state; } + bool click(const UiNode& node, MouseButton button, bool /*dbl*/, + const std::vector&) override { + clicked_ids.push_back(node.id); + click_buttons.push_back(button); + return click_result; + } + bool type_text(const std::string& text) override { + typed_text.push_back(text); return true; + } + bool send_keys(const std::vector& chords) override { + sent_keys.push_back(chords); return true; + } + PngImage screenshot_window(const UiNode*) override { + ++screenshot_window_count; return canned_png; + } + PngImage screenshot_viewport3d(std::optional, std::optional, + std::optional) override { + ++screenshot_viewport_count; return canned_png; + } +}; + +}}} // namespace