mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-11 06:23:08 +00:00
124 lines
3.9 KiB
C++
124 lines
3.9 KiB
C++
#include <catch2/catch_all.hpp>
|
|
#include "slic3r/GUI/Automation/Locator.hpp"
|
|
|
|
using namespace Slic3r::GUI::Automation;
|
|
|
|
namespace {
|
|
UiNode make_tree() {
|
|
UiNode root;
|
|
root.klass = "MainFrame";
|
|
root.path = "MainFrame";
|
|
|
|
UiNode panel;
|
|
panel.klass = "Panel";
|
|
panel.path = "MainFrame/Panel[0]";
|
|
|
|
UiNode slice;
|
|
slice.id = "btn_slice";
|
|
slice.klass = "Button";
|
|
slice.label = "Slice plate";
|
|
slice.path = "MainFrame/Panel[0]/Button[0]";
|
|
|
|
UiNode export_btn;
|
|
export_btn.id = "btn_export";
|
|
export_btn.klass = "Button";
|
|
export_btn.label = "Export";
|
|
export_btn.path = "MainFrame/Panel[0]/Button[1]";
|
|
|
|
UiNode dup; // duplicate label, used for ambiguity tests
|
|
dup.klass = "Button";
|
|
dup.label = "Export";
|
|
dup.path = "MainFrame/Panel[0]/Button[2]";
|
|
|
|
panel.children = {slice, export_btn, dup};
|
|
root.children = {panel};
|
|
return root;
|
|
}
|
|
} // namespace
|
|
|
|
TEST_CASE("flatten yields parents before children", "[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
const auto all = flatten(tree);
|
|
REQUIRE(all.size() == 5);
|
|
CHECK(all.front()->klass == "MainFrame");
|
|
}
|
|
|
|
TEST_CASE("find_matches by exact id returns one", "[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
Target t; t.id = "btn_slice";
|
|
const auto m = find_matches(tree, t);
|
|
REQUIRE(m.size() == 1);
|
|
CHECK(m[0]->label == "Slice plate");
|
|
}
|
|
|
|
TEST_CASE("find_matches by exact path returns one", "[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
Target t; t.path = "MainFrame/Panel[0]/Button[1]";
|
|
const auto m = find_matches(tree, t);
|
|
REQUIRE(m.size() == 1);
|
|
CHECK(m[0]->id == "btn_export");
|
|
}
|
|
|
|
TEST_CASE("find_matches by predicate (label) can be ambiguous",
|
|
"[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
Target t; t.label = "Export";
|
|
const auto m = find_matches(tree, t);
|
|
CHECK(m.size() == 2); // btn_export + the duplicate
|
|
}
|
|
|
|
TEST_CASE("find_matches predicate combines fields (AND)",
|
|
"[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
Target t; t.label = "Export"; t.klass = "Button"; t.id = std::nullopt;
|
|
// id/path absent -> predicate mode. Both fields must match.
|
|
t.id = std::nullopt;
|
|
const auto m = find_matches(tree, t);
|
|
CHECK(m.size() == 2);
|
|
}
|
|
|
|
TEST_CASE("find_matches by name matches id OR label", "[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
Target byId; byId.name = "btn_slice";
|
|
CHECK(find_matches(tree, byId).size() == 1);
|
|
Target byLabel; byLabel.name = "Slice plate";
|
|
CHECK(find_matches(tree, byLabel).size() == 1);
|
|
}
|
|
|
|
TEST_CASE("find_matches not found returns empty", "[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
Target t; t.id = "nope";
|
|
CHECK(find_matches(tree, t).empty());
|
|
}
|
|
|
|
TEST_CASE("resolve_unique success / not-found / ambiguous",
|
|
"[automation][locator]") {
|
|
const auto tree = make_tree();
|
|
int count = -1;
|
|
|
|
Target ok; ok.id = "btn_slice";
|
|
CHECK(resolve_unique(tree, ok, count) != nullptr);
|
|
CHECK(count == 1);
|
|
|
|
Target missing; missing.id = "nope";
|
|
CHECK(resolve_unique(tree, missing, count) == nullptr);
|
|
CHECK(count == 0);
|
|
|
|
Target ambiguous; ambiguous.label = "Export";
|
|
CHECK(resolve_unique(tree, ambiguous, count) == nullptr);
|
|
CHECK(count == 2);
|
|
}
|
|
|
|
TEST_CASE("evaluate_state covers exists/visible/enabled/value",
|
|
"[automation][locator]") {
|
|
UiNode n; n.visible = true; n.enabled = false;
|
|
n.has_value = true; n.value = "PLA";
|
|
|
|
CHECK(evaluate_state(&n, WaitState::Exists, std::nullopt));
|
|
CHECK(evaluate_state(&n, WaitState::Visible, std::nullopt));
|
|
CHECK_FALSE(evaluate_state(&n, WaitState::Enabled, std::nullopt)); // disabled
|
|
CHECK(evaluate_state(&n, WaitState::Value, std::string("PLA")));
|
|
CHECK_FALSE(evaluate_state(&n, WaitState::Value, std::string("ABS")));
|
|
CHECK_FALSE(evaluate_state(nullptr, WaitState::Exists, std::nullopt));
|
|
}
|