diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2024-07-15 22:26:12 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2024-07-15 22:26:12 +0200 |
| commit | 3262b3a337759439f3049b9299be12baf8420750 (patch) | |
| tree | 53d2e71a390662894bca3eb5c9345a59f08fc806 | |
| parent | 7758fbc7522b39bad768abfa728b37c97007ffb6 (diff) | |
| download | turns-3262b3a337759439f3049b9299be12baf8420750.tar.xz turns-3262b3a337759439f3049b9299be12baf8420750.zip | |
turns: add more tests
| -rw-r--r-- | app/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | app/include/turns/app/windows/participant_editor.hpp | 2 | ||||
| -rw-r--r-- | app/src/windows/participant_editor.cpp | 8 | ||||
| -rw-r--r-- | app/tests/windows/main.cpp | 17 | ||||
| -rw-r--r-- | app/tests/windows/participant_editor.cpp | 112 | ||||
| -rw-r--r-- | domain/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | domain/include/turns/domain/turn_order.hpp | 6 | ||||
| -rw-r--r-- | domain/src/turn_order.cpp | 21 | ||||
| -rw-r--r-- | domain/tests/participant.cpp | 12 | ||||
| -rw-r--r-- | domain/tests/turn_order.cpp | 141 |
10 files changed, 290 insertions, 31 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index eaf16b6..1074038 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -68,6 +68,7 @@ install(FILES add_executable("app-tests" "tests/windows/main.cpp" + "tests/windows/participant_editor.cpp" ) target_link_libraries("app-tests" PRIVATE diff --git a/app/include/turns/app/windows/participant_editor.hpp b/app/include/turns/app/windows/participant_editor.hpp index 38b1887..cfa2245 100644 --- a/app/include/turns/app/windows/participant_editor.hpp +++ b/app/include/turns/app/windows/participant_editor.hpp @@ -22,8 +22,6 @@ namespace turns::app::windows auto present(Gtk::Widget * parent) -> void; - auto set_title(Glib::ustring const & value) -> void; - auto signal_finished() -> signal_finished_type; private: diff --git a/app/src/windows/participant_editor.cpp b/app/src/windows/participant_editor.cpp index 49809c6..dd21248 100644 --- a/app/src/windows/participant_editor.cpp +++ b/app/src/windows/participant_editor.cpp @@ -4,6 +4,7 @@ #include <print> +#include <glibmm/i18n.h> #include <gtkmm/editable.h> #include <gtkmm/listboxrow.h> @@ -26,7 +27,7 @@ namespace turns::app::windows adw_spin_row_set_value(m_priority, m_participant->property_priority().get_value()); } - adw_dialog_set_title(m_adw, obj ? lang::edit_participant : lang::add_participant); + adw_dialog_set_title(m_adw, _(obj ? lang::edit_participant : lang::add_participant)); m_finish->signal_clicked().connect(sigc::mem_fun(*this, &participant_editor::handle_finish_clicked)); } @@ -35,11 +36,6 @@ namespace turns::app::windows adw_dialog_present(m_adw, parent->gobj()); } - auto participant_editor::set_title(Glib::ustring const & value) -> void - { - adw_dialog_set_title(m_adw, value.c_str()); - } - auto participant_editor::signal_finished() -> signal_finished_type { return m_signal_finished; diff --git a/app/tests/windows/main.cpp b/app/tests/windows/main.cpp index 8661153..a04a130 100644 --- a/app/tests/windows/main.cpp +++ b/app/tests/windows/main.cpp @@ -12,13 +12,14 @@ #include <glibmm/ustring.h> #include <gtkmm/builder.h> #include <gtkmm/button.h> +#include <gtkmm/listbox.h> #include <gtkmm/menubutton.h> #include <gtkmm/widget.h> namespace turns::app::windows::tests { - TEST_CASE("Newly constructed main window", "[windows]") + TEST_CASE("A freshly constructed main window", "[windows]") { auto locale = GENERATE("en_US.UTF-8", "de_CH.UTF-8"); setlocale(LC_ALL, locale); @@ -26,46 +27,46 @@ namespace turns::app::windows::tests auto builder = Gtk::Builder::create_from_resource("/ch/arknet/Turns/windows/main.ui"); auto instance = Gtk::Builder::get_widget_derived<main>(builder, "main"); - SECTION("construction via builder succeeds") + SECTION("was successfully constructed") { REQUIRE(instance); } - SECTION("the window sub-title is not empty") + SECTION("has a non-empty subtitle") { auto widget = builder->get_widget<Gtk::Widget>("title"); auto adw = ADW_WINDOW_TITLE(widget->gobj()); REQUIRE(adw_window_title_get_subtitle(adw)); } - SECTION("the window sub-title is set according to the active language") + SECTION("has its subtitle set according to the active language") { auto widget = builder->get_widget<Gtk::Widget>("title"); auto adw = ADW_WINDOW_TITLE(widget->gobj()); REQUIRE(adw_window_title_get_subtitle(adw) == Glib::ustring{_(lang::no_active_turn_order)}); } - SECTION("the window title is not empty") + SECTION("has a non-empty title") { auto widget = builder->get_widget<Gtk::Widget>("title"); auto adw = ADW_WINDOW_TITLE(widget->gobj()); REQUIRE(adw_window_title_get_title(adw)); } - SECTION("the window title is set according to the active language") + SECTION("has its title set according to the active language") { auto widget = builder->get_widget<Gtk::Widget>("title"); auto adw = ADW_WINDOW_TITLE(widget->gobj()); REQUIRE(adw_window_title_get_title(adw) == Glib::ustring{_(lang::turns)}); } - SECTION("the add_participant button has the correct tooltip") + SECTION("has its add_participant button's tooltip set according to the active language") { auto widget = builder->get_widget<Gtk::Button>("add_participant"); REQUIRE(widget->get_tooltip_text() == Glib::ustring{_(lang::add_participant)}); } - SECTION("the open_main_menu button has the correct tooltip") + SECTION("as its open_main_menu button's tooltip set according to the active language") { auto widget = builder->get_widget<Gtk::MenuButton>("open_main_menu"); REQUIRE(widget->get_tooltip_text() == Glib::ustring{_(lang::main_menu)}); diff --git a/app/tests/windows/participant_editor.cpp b/app/tests/windows/participant_editor.cpp new file mode 100644 index 0000000..15c9975 --- /dev/null +++ b/app/tests/windows/participant_editor.cpp @@ -0,0 +1,112 @@ +#include "turns/app/windows/participant_editor.hpp" + +#include "turns/domain/participant.hpp" +#include "turns/lang/messages.hpp" + +#include <catch2/catch_test_macros.hpp> +#include <catch2/generators/catch_generators.hpp> + +#include <string> + +#include <adwaita.h> +#include <glibmm/i18n.h> +#include <glibmm/ustring.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/listboxrow.h> +#include <gtkmm/widget.h> +#include <gtkmm/window.h> + +namespace turns::app::windows::tests +{ + + TEST_CASE("A freshly constructed participant editor without a participant", "[windows]") + { + auto locale = GENERATE("en_US.UTF-8", "de_CH.UTF-8"); + setlocale(LC_ALL, locale); + + auto builder = Gtk::Builder::create_from_resource("/ch/arknet/Turns/windows/participant_editor.ui"); + auto instance = Gtk::Builder::get_widget_derived<participant_editor>(builder, "participant_editor"); + auto window = Gtk::Window{}; + + SECTION("was successfully constructed") + { + REQUIRE(instance); + } + + SECTION("has a non-empty title") + { + auto widget = ADW_DIALOG(instance->gobj()); + REQUIRE(adw_dialog_get_title(widget)); + } + + SECTION("has its title set according to the active language") + { + auto widget = ADW_DIALOG(instance->gobj()); + REQUIRE(adw_dialog_get_title(widget) == Glib::ustring{_(lang::add_participant)}); + } + + SECTION("has an empty name field") + { + auto widget = GTK_EDITABLE(builder->get_widget<Gtk::ListBoxRow>("name")->gobj()); + REQUIRE(Glib::ustring{gtk_editable_get_text(widget)}.empty()); + } + + SECTION("has a zero priority field") + { + auto widget = ADW_SPIN_ROW(builder->get_widget<Gtk::ListBoxRow>("priority")->gobj()); + REQUIRE(adw_spin_row_get_value(widget) == 0); + } + + SECTION("allows binding to the finished signal") + { + REQUIRE((instance->signal_finished().connect([](auto, auto){})).connected()); + } + } + + TEST_CASE("A freshly constructed participant editor with a participant", "[windows]") + { + auto locale = GENERATE("en_US.UTF-8", "de_CH.UTF-8"); + setlocale(LC_ALL, locale); + + auto participant = domain::participant::create("Qibi Babblebranch", 12); + auto builder = Gtk::Builder::create_from_resource("/ch/arknet/Turns/windows/participant_editor.ui"); + auto instance = Gtk::Builder::get_widget_derived<participant_editor>(builder, "participant_editor", participant); + auto window = Gtk::Window{}; + + SECTION("was successfully constructed") + { + REQUIRE(instance); + } + + SECTION("has a non-empty title") + { + auto widget = ADW_DIALOG(instance->gobj()); + REQUIRE(adw_dialog_get_title(widget)); + } + + SECTION("has its title set according to the active language") + { + auto widget = ADW_DIALOG(instance->gobj()); + REQUIRE(adw_dialog_get_title(widget) == Glib::ustring{_(lang::edit_participant)}); + } + + SECTION("has its name field set according to its participant") + { + auto widget = GTK_EDITABLE(builder->get_widget<Gtk::ListBoxRow>("name")->gobj()); + REQUIRE(gtk_editable_get_text(widget) == participant->get_name()); + } + + SECTION("has its priority field set according to its participant") + { + auto widget = ADW_SPIN_ROW(builder->get_widget<Gtk::ListBoxRow>("priority")->gobj()); + REQUIRE(adw_spin_row_get_value(widget) == participant->get_priority()); + } + + SECTION("allows binding to the finished signal") + { + REQUIRE((instance->signal_finished().connect([](auto, auto){})).connected()); + } + } + +} // namespace turns::app::windows::tests
\ No newline at end of file diff --git a/domain/CMakeLists.txt b/domain/CMakeLists.txt index 066f638..b33ae96 100644 --- a/domain/CMakeLists.txt +++ b/domain/CMakeLists.txt @@ -37,6 +37,7 @@ target_link_options("domain" PRIVATE add_executable("domain-tests" "tests/participant.cpp" + "tests/turn_order.cpp" ) target_link_libraries("domain-tests" diff --git a/domain/include/turns/domain/turn_order.hpp b/domain/include/turns/domain/turn_order.hpp index cb51af6..d231436 100644 --- a/domain/include/turns/domain/turn_order.hpp +++ b/domain/include/turns/domain/turn_order.hpp @@ -15,14 +15,16 @@ namespace turns::domain using super = Gio::ListStore<participant>; using super::super; - using super::append; using super::remove; auto static create() -> Glib::RefPtr<turn_order>; + auto append(Glib::RefPtr<participant> item) -> void; auto append(Glib::ustring const & name, float priority) -> void; auto remove(Glib::RefPtr<participant> item) -> void; - auto sort() -> void; + + private: + using super::sort; }; } // namespace turns::domain diff --git a/domain/src/turn_order.cpp b/domain/src/turn_order.cpp index 454e27a..eddd468 100644 --- a/domain/src/turn_order.cpp +++ b/domain/src/turn_order.cpp @@ -23,6 +23,10 @@ namespace turns::domain } return -1; }; + + auto constexpr equal_comparator = [](auto lhs, auto rhs) { + return (lhs->get_name() == rhs->get_name()) && (lhs->get_priority() && rhs->get_priority()); + }; } // namespace auto turn_order::create() -> Glib::RefPtr<turn_order> @@ -30,11 +34,19 @@ namespace turns::domain return Glib::make_refptr_for_instance(new turn_order{}); } + auto turn_order::append(Glib::RefPtr<participant> item) -> void + { + if (auto [found, index] = find(item, equal_comparator); !found) + { + insert_sorted(item, comparator); + } + } + auto turn_order::append(Glib::ustring const & name, float priority) -> void { auto participant = participant::create(name, priority); - participant->property_priority().signal_changed().connect([this] { sort(); }); - insert_sorted(participant, comparator); + participant->property_priority().signal_changed().connect([this] { sort(comparator); }); + append(participant); } auto turn_order::remove(Glib::RefPtr<participant> item) -> void @@ -45,9 +57,4 @@ namespace turns::domain } } - auto turn_order::sort() -> void - { - super::sort(comparator); - } - } // namespace turns::domain
\ No newline at end of file diff --git a/domain/tests/participant.cpp b/domain/tests/participant.cpp index e9e7c46..268b395 100644 --- a/domain/tests/participant.cpp +++ b/domain/tests/participant.cpp @@ -22,24 +22,24 @@ namespace turns::domain::tests SECTION("the name can be read") { - REQUIRE(instance.property_name() == constructed_name); + REQUIRE(instance.get_name() == constructed_name); } SECTION("the name can be changed") { - instance.property_name() = "replaced"; - REQUIRE(instance.property_name() == "replaced"); + instance.set_name("replaced"); + REQUIRE(instance.get_name() == "replaced"); } SECTION("the priority can be read") { - REQUIRE(instance.property_priority() == constructed_priority); + REQUIRE(instance.get_priority() == constructed_priority); } SECTION("the priority can be changed") { - instance.property_priority() = 8; - REQUIRE(instance.property_priority() == 8); + instance.set_priority(8); + REQUIRE(instance.get_priority() == 8); } SECTION("can be compared with another participant") diff --git a/domain/tests/turn_order.cpp b/domain/tests/turn_order.cpp new file mode 100644 index 0000000..7172ffc --- /dev/null +++ b/domain/tests/turn_order.cpp @@ -0,0 +1,141 @@ +#include "turns/domain/turn_order.hpp" + +#include "turns/domain/participant.hpp" + +#include <catch2/catch_test_macros.hpp> + +#include <compare> + +#include <glibmm/init.h> + +namespace turns::domain::tests +{ + + TEST_CASE("A freshly constructed turn order") + { + auto instance = turn_order{}; + + SECTION("can be created") + { + REQUIRE(turn_order::create()); + } + + SECTION("has 0 items") + { + REQUIRE(instance.get_n_items() == 0); + } + + SECTION("accepts a new participant in form of a refptr") + { + instance.append(participant::create("Honey Bunches of Oats", 12)); + REQUIRE(instance.get_n_items() == 1); + } + + SECTION("accepts a new participant in form of components") + { + instance.append("River along the Field", 14); + REQUIRE(instance.get_n_items() == 1); + } + + SECTION("does nothing when trying to remove an item by refptr if no items were added beforehand") + { + instance.remove(participant::create("Patch in the Forest", 3)); + REQUIRE(instance.get_n_items() == 0); + } + + SECTION("does nothing when trying to remove an item by index if no items were added beforehand") + { + instance.remove(5); + REQUIRE(instance.get_n_items() == 0); + } + + SECTION("allows the removal of an item by refptr if the same item was added beforehand") + { + auto item = participant::create("Blank Canvas", 23); + instance.append(item); + instance.remove(item); + REQUIRE(instance.get_n_items() == 0); + } + + SECTION("does nothing when trying to remove an item by refptr that was not added beforehand") + { + auto item = participant::create("Blank Canvas", 23); + instance.append(item); + instance.remove(participant::create("Spell of Rain", 6)); + REQUIRE(instance.get_n_items() == 1); + } + + SECTION("automatically sorts appended refptrs in descending order of priority") + { + SECTION("when appending the higher one last") + { + instance.append(participant::create("Snow on the Field", 2)); + instance.append(participant::create("Bees behind the Cottage", 8)); + REQUIRE(instance.get_item(0)->get_name() == "Bees behind the Cottage"); + } + + SECTION("when appending the higher one first") + { + instance.append(participant::create("Bees behind the Cottage", 8)); + instance.append(participant::create("Snow on the Field", 2)); + REQUIRE(instance.get_item(0)->get_name() == "Bees behind the Cottage"); + } + + SECTION("keeping the insertion order when appending items with equal priority") + { + instance.append(participant::create("Snow on the Field", 8)); + instance.append(participant::create("Bees behind the Cottage", 8)); + REQUIRE(instance.get_item(0)->get_name() == "Snow on the Field"); + } + } + + SECTION("automatically sorts elements appended by components in descending order of priority") + { + SECTION("when appending the higher one last") + { + instance.append("Tree Blossom", 6); + instance.append("Fish in the River", 12); + REQUIRE(instance.get_item(0)->get_name() == "Fish in the River"); + } + + SECTION("when appending the higher one first") + { + instance.append("Fish in the River", 12); + instance.append("Tree Blossom", 6); + REQUIRE(instance.get_item(0)->get_name() == "Fish in the River"); + } + + SECTION("keeping the insertion order when appending items with equal priority") + { + instance.append("Fish in the River", 6); + instance.append("Tree Blossom", 6); + REQUIRE(instance.get_item(0)->get_name() == "Fish in the River"); + } + } + + SECTION("does not accept the same item twice by the same refptr") + { + auto item = participant::create("Angelic Berry", 9); + instance.append(item); + instance.append(item); + REQUIRE(instance.get_n_items() == 1); + } + + SECTION("does not accept the same item twice by different refptrs") + { + auto item_one = participant::create("Misty Meadow", 14.2); + auto item_two = participant::create("Misty Meadow", 14.2); + instance.append(item_one); + instance.append(item_two); + REQUIRE(instance.get_n_items() == 1); + } + + SECTION("does not accept the same item twice by components") + { + instance.append("Frozen Apple Tree", 2.1); + instance.append("Frozen Apple Tree", 2.1); + REQUIRE(instance.get_n_items() == 1); + } + } + +} // namespace turns::domain::tests
\ No newline at end of file |
