diff --git a/src/test/GUI/test_field_point3.cpp b/src/test/GUI/test_field_point3.cpp new file mode 100644 index 000000000..aaeedfd15 --- /dev/null +++ b/src/test/GUI/test_field_point3.cpp @@ -0,0 +1,376 @@ +#include + +#ifndef WX_PRECOMP +#include "wx/app.h" +#include "wx/sizer.h" +#include "wx/uiaction.h" +#endif // WX_PRECOMP + +#include +#include + +#include "testableframe.h" +#include "OptionsGroup/Field.hpp" +#include "ConfigBase.hpp" +#include "Point.hpp" + +using namespace std::string_literals; + +SCENARIO( "UI_Point3: default values from options and basic accessor methods") { + wxTestableFrame* old = dynamic_cast(wxTheApp->GetTopWindow()); + old->Destroy(); + wxTheApp->SetTopWindow(new wxTestableFrame()); + wxUIActionSimulator sim; + wxMilliSleep(500); + + GIVEN( "A UI point method and a X,Y coordinate (3.2, 10.2) as the default_value") { + auto simple_option {ConfigOptionDef()}; + auto* default_point {new ConfigOptionPoint(Pointf(3.2, 10.2))}; + simple_option.default_value = default_point; + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + + THEN( "get_string() returns '3.2;10.2;0.0'.") { + REQUIRE(test_field.get_string() == "3.2;10.2;0.0"s); + } + THEN( "get_point() yields a Pointf structure with x = 3.2, y = 10.2") { + REQUIRE(test_field.get_point().x == 3.2); + REQUIRE(test_field.get_point().y == 10.2); + } + THEN( "get_point3() yields a Pointf3 structure with x = 3.2, y = 10.2, z = 0.0") { + REQUIRE(test_field.get_point3().x == 3.2); + REQUIRE(test_field.get_point3().y == 10.2); + REQUIRE(test_field.get_point3().z == 0.0); + } + } + GIVEN( "A UI point, coordinate in X/Y/Z and a tooltip in simple_option") { + auto simple_option {ConfigOptionDef()}; + auto* default_point {new ConfigOptionPoint(Pointf3(3.2, 10.2, 0.2))}; + simple_option.default_value = default_point; + + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + THEN( "Tooltip for both labels and textctrls matches simple_option") { + REQUIRE(test_field.ctrl_x()->GetToolTipText().ToStdString() == simple_option.tooltip ); + REQUIRE(test_field.lbl_x()->GetToolTipText().ToStdString() == simple_option.tooltip ); + REQUIRE(test_field.ctrl_y()->GetToolTipText().ToStdString() == simple_option.tooltip ); + REQUIRE(test_field.lbl_y()->GetToolTipText().ToStdString() == simple_option.tooltip ); + REQUIRE(test_field.ctrl_z()->GetToolTipText().ToStdString() == simple_option.tooltip ); + REQUIRE(test_field.lbl_z()->GetToolTipText().ToStdString() == simple_option.tooltip ); + } + THEN( "get_point3() yields a Pointf3 structure with x = 3.2, y = 10.2, z = 0.2") { + REQUIRE(test_field.get_point3().x == 3.2); + REQUIRE(test_field.get_point3().y == 10.2); + REQUIRE(test_field.get_point3().z == 0.2); + } + THEN( "get_point() yields a Pointf structure with x = 3.2, y = 10.2") { + REQUIRE(test_field.get_point().x == 3.2); + REQUIRE(test_field.get_point().y == 10.2); + } + } +} + +SCENARIO( "UI_Point3: set_value works with several types of inputs") { + wxTestableFrame* old = dynamic_cast(wxTheApp->GetTopWindow()); + old->Destroy(); + wxTheApp->SetTopWindow(new wxTestableFrame()); + wxUIActionSimulator sim; + wxMilliSleep(500); + GIVEN( "A UI point method with no default value.") { + auto simple_option {ConfigOptionDef()}; + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + WHEN( "set_value is called with a Pointf(19.0, 2.1)") { + test_field.set_value(Pointf(19.0, 2.1)); + THEN( "get_point3() returns a Pointf3(19.0, 2.1, 0.0)") { + REQUIRE(test_field.get_point3() == Pointf3(19.0, 2.1, 0.0)); + } + THEN( "get_point() returns a Pointf(19.0, 2.1)") { + REQUIRE(test_field.get_point() == Pointf(19.0, 2.1)); + } + THEN( "get_string() returns '19.0;2.1'") { + REQUIRE(test_field.get_string() == "19.0;2.1;0.0"s); + } + THEN( "X TextCtrl contains X coordinate") { + REQUIRE(test_field.ctrl_x()->GetValue() == wxString("19.0"s)); + } + THEN( "Y TextCtrl contains Y coordinate") { + REQUIRE(test_field.ctrl_y()->GetValue() == wxString("2.1"s)); + } + THEN( "Z TextCtrl contains Z coordinate") { + REQUIRE(test_field.ctrl_z()->GetValue() == wxString("0.0"s)); + } + } + WHEN( "set_value is called with a Pointf3(19.0, 2.1, 0.6)") { + test_field.set_value(Pointf3(19.0, 2.1, 0.6)); + THEN( "get_point3() returns a Pointf3(19.0, 2.1, 0.6)") { + REQUIRE(test_field.get_point3() == Pointf3(19.0, 2.1, 0.6)); + } + THEN( "get_point() returns a Pointf(19.0, 2.1)") { + REQUIRE(test_field.get_point() == Pointf(19.0, 2.1)); + } + THEN( "get_string() returns '19.0;2.1;0.6'") { + REQUIRE(test_field.get_string() == "19.0;2.1;0.6"s); + } + THEN( "X TextCtrl contains X coordinate") { + REQUIRE(test_field.ctrl_x()->GetValue() == wxString("19.0"s)); + } + THEN( "Y TextCtrl contains Y coordinate") { + REQUIRE(test_field.ctrl_y()->GetValue() == wxString("2.1"s)); + } + THEN( "Z TextCtrl contains Z coordinate") { + REQUIRE(test_field.ctrl_z()->GetValue() == wxString("0.6"s)); + } + } + WHEN( "set_value is called with a string of the form '30.9;211.2;411.0'") { + test_field.set_value("30.9;211.2;411.0"s); + THEN( "get_point3() returns a Pointf3(30.9, 211.2, 411.0)") { + REQUIRE(test_field.get_point3() == Pointf(30.9, 211.2, 411.0)); + } + THEN( "get_point() returns a Pointf(30.9, 211.2)") { + REQUIRE(test_field.get_point() == Pointf(30.9, 211.2)); + } + THEN( "get_string() returns '30.9;211.2;411.0'") { + REQUIRE(test_field.get_string() == "30.9;211.2;411.0"s); + } + THEN( "X TextCtrl contains X coordinate") { + REQUIRE(test_field.ctrl_x()->GetValue() == wxString("30.9"s)); + } + THEN( "Y TextCtrl contains Y coordinate") { + REQUIRE(test_field.ctrl_y()->GetValue() == wxString("211.2"s)); + } + THEN( "Z TextCtrl contains Z coordinate") { + REQUIRE(test_field.ctrl_z()->GetValue() == wxString("411.0"s)); + } + } + WHEN( "set_value is called with a wxString of the form '30.9;211.2;411.0'") { + test_field.set_value(wxString("30.9;211.2;411.0"s)); + THEN( "get_point3() returns a Pointf3(30.9, 211.2, 411.0)") { + REQUIRE(test_field.get_point3() == Pointf3(30.9, 211.2, 411.0)); + } + THEN( "get_point() returns a Pointf(30.9, 211.2)") { + REQUIRE(test_field.get_point() == Pointf(30.9, 211.2)); + } + THEN( "get_string() returns '30.9;211.2;411.0'") { + REQUIRE(test_field.get_string() == "30.9;211.2;411.0"s); + } + THEN( "X TextCtrl contains X coordinate") { + REQUIRE(test_field.ctrl_x()->GetValue() == wxString("30.9"s)); + } + THEN( "Y TextCtrl contains Y coordinate") { + REQUIRE(test_field.ctrl_y()->GetValue() == wxString("211.2"s)); + } + THEN( "Z TextCtrl contains Z coordinate") { + REQUIRE(test_field.ctrl_z()->GetValue() == wxString("411.0"s)); + } + } + } +} + +SCENARIO( "UI_Point3: Event responses") { + wxTestableFrame* old = dynamic_cast(wxTheApp->GetTopWindow()); + old->Destroy(); + wxTheApp->SetTopWindow(new wxTestableFrame()); + wxMilliSleep(250); + GIVEN ( "A UI_Point3 with no default value and a registered on_change method that increments a counter.") { + auto simple_option {ConfigOptionDef()}; + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + auto event_count {0}; + auto changefunc {[&event_count] (const std::string& opt_id, std::tuple value) { event_count++; }}; + auto killfunc {[&event_count](const std::string& opt_id) { event_count++; }}; + + test_field.on_change = changefunc; + test_field.on_kill_focus = killfunc; + + test_field.disable_change_event = false; + + WHEN( "kill focus event is received on X") { + event_count = 0; + auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.ctrl_x()->GetId())}; + ev.SetEventObject(test_field.ctrl_x()); + test_field.ctrl_x()->ProcessWindowEvent(ev); + THEN( "on_kill_focus is executed.") { + REQUIRE(event_count == 2); + } + } + WHEN( "kill focus event is received on Y") { + event_count = 0; + auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.ctrl_y()->GetId())}; + ev.SetEventObject(test_field.ctrl_y()); + test_field.ctrl_y()->ProcessWindowEvent(ev); + THEN( "on_kill_focus is executed.") { + REQUIRE(event_count == 2); + } + } + WHEN( "kill focus event is received on Z") { + event_count = 0; + auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.ctrl_z()->GetId())}; + ev.SetEventObject(test_field.ctrl_z()); + test_field.ctrl_z()->ProcessWindowEvent(ev); + THEN( "on_kill_focus is executed.") { + REQUIRE(event_count == 2); + } + } + WHEN( "enter key pressed event is received on X") { + event_count = 0; + auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.ctrl_x()->GetId())}; + ev.SetEventObject(test_field.ctrl_x()); + test_field.ctrl_x()->ProcessWindowEvent(ev); + THEN( "on_change is executed.") { + REQUIRE(event_count == 1); + } + } + WHEN( "enter key pressed event is received on Y") { + event_count = 0; + auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.ctrl_y()->GetId())}; + ev.SetEventObject(test_field.ctrl_y()); + test_field.ctrl_y()->ProcessWindowEvent(ev); + THEN( "on_change is executed.") { + REQUIRE(event_count == 1); + } + } + WHEN( "enter key pressed event is received on Z") { + event_count = 0; + auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.ctrl_z()->GetId())}; + ev.SetEventObject(test_field.ctrl_z()); + test_field.ctrl_z()->ProcessWindowEvent(ev); + THEN( "on_change is executed.") { + REQUIRE(event_count == 1); + } + } + } + GIVEN ( "A UI_Point3 with no default value and a registered on_change method that increments a counter only when disable_change_event = false.") { + auto simple_option {ConfigOptionDef()}; + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + auto event_count {0}; + auto changefunc {[&event_count] (const std::string& opt_id, std::tuple value) { event_count++; }}; + auto killfunc {[&event_count](const std::string& opt_id) { event_count += 1; }}; + + test_field.on_change = changefunc; + test_field.on_kill_focus = killfunc; + test_field.disable_change_event = true; + + WHEN( "kill focus event is received on X") { + event_count = 0; + auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.ctrl_x()->GetId())}; + ev.SetEventObject(test_field.ctrl_x()); + test_field.ctrl_x()->ProcessWindowEvent(ev); + THEN( "on_kill_focus is executed.") { + REQUIRE(event_count == 1); + } + } + WHEN( "kill focus event is received on Y") { + event_count = 0; + auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.ctrl_y()->GetId())}; + ev.SetEventObject(test_field.ctrl_y()); + test_field.ctrl_y()->ProcessWindowEvent(ev); + THEN( "on_kill_focus is executed.") { + REQUIRE(event_count == 1); + } + } + WHEN( "kill focus event is received on Z") { + event_count = 0; + auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.ctrl_z()->GetId())}; + ev.SetEventObject(test_field.ctrl_z()); + test_field.ctrl_z()->ProcessWindowEvent(ev); + THEN( "on_kill_focus is executed.") { + REQUIRE(event_count == 1); + } + } + WHEN( "enter key pressed event is received on X") { + event_count = 0; + auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.ctrl_x()->GetId())}; + ev.SetEventObject(test_field.ctrl_x()); + test_field.ctrl_x()->ProcessWindowEvent(ev); + THEN( "on_change is not executed.") { + REQUIRE(event_count == 0); + } + } + WHEN( "enter key pressed event is received on Y") { + event_count = 0; + auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.ctrl_y()->GetId())}; + ev.SetEventObject(test_field.ctrl_y()); + test_field.ctrl_y()->ProcessWindowEvent(ev); + THEN( "on_change is not executed.") { + REQUIRE(event_count == 0); + } + } + WHEN( "enter key pressed event is received on Z") { + event_count = 0; + auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.ctrl_z()->GetId())}; + ev.SetEventObject(test_field.ctrl_z()); + test_field.ctrl_z()->ProcessWindowEvent(ev); + THEN( "on_change is not executed.") { + REQUIRE(event_count == 0); + } + } + } +} + +SCENARIO( "UI_Point3: Enable/Disable") { + wxTestableFrame* old = dynamic_cast(wxTheApp->GetTopWindow()); + old->Destroy(); + wxTheApp->SetTopWindow(new wxTestableFrame()); + wxMilliSleep(250); + GIVEN ( "A UI_Point3 with no default value.") { + auto simple_option {ConfigOptionDef()}; + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + WHEN( "disable() is called") { + test_field.disable(); + THEN( "IsEnabled == False for X and Y and Z textctrls") { + REQUIRE(test_field.ctrl_x()->IsEnabled() == false); + REQUIRE(test_field.ctrl_y()->IsEnabled() == false); + REQUIRE(test_field.ctrl_z()->IsEnabled() == false); + } + } + WHEN( "enable() is called") { + test_field.enable(); + THEN( "IsEnabled == True for X and Y and Z textctrls") { + REQUIRE(test_field.ctrl_x()->IsEnabled() == true); + REQUIRE(test_field.ctrl_y()->IsEnabled() == true); + REQUIRE(test_field.ctrl_z()->IsEnabled() == true); + } + } + WHEN( "toggle() is called with false argument") { + test_field.toggle(false); + THEN( "IsEnabled == False for X and Y and Z textctrls") { + REQUIRE(test_field.ctrl_x()->IsEnabled() == false); + REQUIRE(test_field.ctrl_y()->IsEnabled() == false); + REQUIRE(test_field.ctrl_z()->IsEnabled() == false); + } + } + WHEN( "toggle() is called with true argument") { + test_field.toggle(true); + THEN( "IsEnabled == True for X and Y and Z textctrls") { + REQUIRE(test_field.ctrl_x()->IsEnabled() == true); + REQUIRE(test_field.ctrl_y()->IsEnabled() == true); + REQUIRE(test_field.ctrl_z()->IsEnabled() == true); + } + } + } +} + +SCENARIO( "UI_Point3: get_sizer()") { + wxTestableFrame* old = dynamic_cast(wxTheApp->GetTopWindow()); + old->Destroy(); + wxTheApp->SetTopWindow(new wxTestableFrame()); + wxMilliSleep(250); + GIVEN ( "A UI_Point3 with no default value.") { + auto simple_option {ConfigOptionDef()}; + auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; + WHEN( "get_sizer() is called") { + THEN( "get_sizer() returns a wxSizer that has 6 direct children in it that are Windows.") { + REQUIRE(test_field.get_sizer()->GetItemCount() == 6); + auto tmp {test_field.get_sizer()->GetChildren().begin()}; + REQUIRE((*tmp)->IsWindow() == true); + tmp++; + REQUIRE((*tmp)->IsWindow() == true); + tmp++; + REQUIRE((*tmp)->IsWindow() == true); + tmp++; + REQUIRE((*tmp)->IsWindow() == true); + tmp++; + REQUIRE((*tmp)->IsWindow() == true); + tmp++; + REQUIRE((*tmp)->IsWindow() == true); + } + } + } +}