diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/glib-fixture.h | 24 | ||||
-rw-r--r-- | tests/test-notification.cpp | 94 |
2 files changed, 118 insertions, 0 deletions
diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h index efc8d17..eb2a8c5 100644 --- a/tests/glib-fixture.h +++ b/tests/glib-fixture.h @@ -20,6 +20,7 @@ #ifndef INDICATOR_DATETIME_TESTS_GLIB_FIXTURE_H #define INDICATOR_DATETIME_TESTS_GLIB_FIXTURE_H +#include <chrono> #include <functional> // std::function #include <map> #include <memory> // std::shared_ptr @@ -198,6 +199,29 @@ class GlibFixture : public ::testing::Test } GMainLoop * loop; + + using source_func = std::function<gboolean()>; + + void idle_add(source_func&& func) + { + g_idle_add_full( + G_PRIORITY_DEFAULT_IDLE, + [](gpointer gf){return (*static_cast<source_func*>(gf))();}, + new std::function<gboolean()>(func), + [](gpointer gf){delete static_cast<source_func*>(gf);} + ); + } + + void timeout_add(source_func&& func, std::chrono::milliseconds msec) + { + g_timeout_add_full( + G_PRIORITY_DEFAULT, + msec.count(), + [](gpointer gf){return (*static_cast<source_func*>(gf))();}, + new std::function<gboolean()>(func), + [](gpointer gf){delete static_cast<source_func*>(gf);} + ); + } }; #endif /* INDICATOR_DATETIME_TESTS_GLIB_FIXTURE_H */ diff --git a/tests/test-notification.cpp b/tests/test-notification.cpp index 74a0b92..f31dcf2 100644 --- a/tests/test-notification.cpp +++ b/tests/test-notification.cpp @@ -194,3 +194,97 @@ TEST_F(NotificationFixture,Notification) } } } + + +TEST_F(NotificationFixture,Response) +{ + // create the world + make_interactive(); + auto ne = std::make_shared<ayatana::indicator::notifications::Engine>(APP_NAME); + auto sb = std::make_shared<ayatana::indicator::notifications::DefaultSoundBuilder>(); + auto settings = std::make_shared<Settings>(); + int next_notification_id {FIRST_NOTIFY_ID}; + + // set a response callback that remembers what response we got + bool on_response_called {}; + Snap::Response response {}; + auto on_response = [this, &on_response_called, &response] + (const Appointment&, const Alarm&, const Snap::Response& r){ + on_response_called = true; + response = r; + g_idle_add(quit_idle, loop); + }; + + // our tests! + const struct { + Appointment appt; + std::vector<std::string> expected_actions; + std::string action; + Snap::Response expected_response; + } tests[] = { + { appt, {"show-app"}, "show-app", Snap::Response::ShowApp }, + { ualarm, {"none", "snooze"}, "snooze", Snap::Response::Snooze }, + { ualarm, {"none", "snooze"}, "none", Snap::Response::None } + }; + + + // walk through the tests + for (const auto& test : tests) + { + // wait for previous iterations' bus noise to finish and reset the counters + GError* error {}; + wait_msec(500); + dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error); + g_assert_no_error(error); + on_response_called = false; + + // create a snap decision + auto snap = create_snap(ne, sb, settings); + (*snap)(test.appt, test.appt.alarms.front(), on_response); + + // wait for the notification to show up + EXPECT_METHOD_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY); + + // test that Notify was called the right number of times + static constexpr int expected_num_notify_calls {1}; + guint num_notify_calls {}; + const auto notify_calls = dbus_test_dbus_mock_object_get_method_calls( + notify_mock, + notify_obj, + METHOD_NOTIFY, + &num_notify_calls, + &error); + g_assert_no_error(error); + EXPECT_EQ(expected_num_notify_calls, num_notify_calls); + + // test that Notify was called with the correct list of actions + if (num_notify_calls > 0) { + std::vector<std::string> actions; + const gchar** as {nullptr}; + g_variant_get_child(notify_calls[0].params, 5, "^a&s", &as); + for (int i=0; as && as[i]; i+=2) // actions are in pairs of (name, i18n), skip the i18n + actions.push_back(as[i]); + EXPECT_EQ(test.expected_actions, actions); + } + + // make the notification mock tell the world that the user invoked an action + const auto notification_id {next_notification_id++}; + idle_add([this, notification_id, test](){ + GError* err {}; + dbus_test_dbus_mock_object_emit_signal(notify_mock, notify_obj, "ActionInvoked", + G_VARIANT_TYPE("(us)"), + g_variant_new("(us)", guint(notification_id), test.action.c_str()), + &err); + dbus_test_dbus_mock_object_emit_signal(notify_mock, notify_obj, "NotificationClosed", + G_VARIANT_TYPE("(uu)"), + g_variant_new("(uu)", guint(notification_id), guint(NOTIFICATION_CLOSED_DISMISSED)), + &err); + g_assert_no_error(err); + return G_SOURCE_REMOVE; + }); + + // confirm that the response callback got the right response + EXPECT_TRUE(wait_for([&on_response_called](){return on_response_called;})); + EXPECT_EQ(int(test.expected_response), int(response)) << "notification_id " << notification_id; + } +} |