/* * Copyright 2014-2016 Canonical Ltd. * Copyright 2021 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Charles Kerr * Robert Tari */ #include #include #include #include "notification-fixture.h" /*** **** ***/ using namespace ayatana::indicator::datetime; namespace { static constexpr char const * APP_NAME {"indicator-datetime-service"}; gboolean quit_idle (gpointer gloop) { g_main_loop_quit(static_cast(gloop)); return G_SOURCE_REMOVE; } } /*** **** ***/ TEST_F(NotificationFixture,Notification) { // Feed different combinations of system settings, // indicator-datetime settings, and event types, // then see if notifications and haptic feedback behave as expected. auto settings = std::make_shared(); auto ne = std::make_shared(APP_NAME); auto sb = std::make_shared(); auto func = [this](const Appointment&, const Alarm&, const Snap::Response&){g_idle_add(quit_idle, loop);}; // combinatorial factor #1: event type struct { Appointment appt; const char* icon_name; const char* prefix; bool expected_notify_called; bool expected_vibrate_called; } test_appts[] = { { appt, "calendar-app", "Event", true, true }, { ualarm, "alarm-clock", "Alarm", true, true } }; // combinatorial factor #2: indicator-datetime's haptic mode struct { const char* haptic_mode; bool expected_notify_called; bool expected_vibrate_called; } test_haptics[] = { { "none", true, false }, { "pulse", true, true } }; // combinatorial factor #3: system settings' "other vibrations" enabled struct { bool other_vibrations; bool expected_notify_called; bool expected_vibrate_called; } test_other_vibrations[] = { { true, true, true }, { false, true, false } }; // combinatorial factor #4: system settings' notifications disabled struct { bool cal_notification_enabled; // calendar app can trigger notifications std::set expected_notify_called; // do we expect the notification to show? std::set expected_vibrate_called; // do we expect the phone to vibrate? } test_cal_disabled[] = { { true, std::set{ Appointment::Type::ALARM, Appointment::Type::EVENT }, std::set{ Appointment::Type::ALARM, Appointment::Type::EVENT } }, { false, std::set{ Appointment::Type::ALARM }, std::set{ Appointment::Type::ALARM } } }; for (const auto& test_appt : test_appts) { for (const auto& test_haptic : test_haptics) { for (const auto& test_vibes : test_other_vibrations) { for (const auto& test_disabled : test_cal_disabled) { const bool expected_notify_called = test_appt.expected_notify_called && test_vibes.expected_notify_called && (test_disabled.expected_notify_called.count(test_appt.appt.type) > 0) && test_haptic.expected_notify_called; const bool expected_vibrate_called = test_appt.expected_vibrate_called && test_vibes.expected_vibrate_called && (test_disabled.expected_vibrate_called.count(test_appt.appt.type) > 0) && test_haptic.expected_vibrate_called; // set test case properties: cal_notification_enabled settings->cal_notification_enabled.set(test_disabled.cal_notification_enabled); settings->cal_notification_sounds.set(test_disabled.cal_notification_enabled); settings->cal_notification_vibrations.set(test_disabled.cal_notification_enabled); settings->cal_notification_bubbles.set(test_disabled.cal_notification_enabled); settings->cal_notification_list.set(test_disabled.cal_notification_enabled); // set test case properties: haptic mode settings->alarm_haptic.set(test_haptic.haptic_mode); // set test case properties: other-vibrations flag // (and wait for the PropertiesChanged signal so we know the dbusmock got it) GError * error {}; dbus_test_dbus_mock_object_update_property(as_mock, as_obj, PROP_OTHER_VIBRATIONS, g_variant_new_boolean(test_vibes.other_vibrations), &error); g_assert_no_error(error); // wait for previous iterations' bus noise to finish and reset the counters wait_msec(500); dbus_test_dbus_mock_object_clear_method_calls(haptic_mock, haptic_obj, &error); dbus_test_dbus_mock_object_clear_method_calls(notify_mock, notify_obj, &error); g_assert_no_error(error); // run the test auto snap = create_snap(ne, sb, settings); (*snap)(test_appt.appt, appt.alarms.front(), func); // confirm that the notification was as expected if (expected_notify_called) { EXPECT_METHOD_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY); } else { EXPECT_METHOD_NOT_CALLED_EVENTUALLY(notify_mock, notify_obj, METHOD_NOTIFY); } // confirm that the vibration was as expected if (expected_vibrate_called) { EXPECT_METHOD_CALLED_EVENTUALLY(haptic_mock, haptic_obj, HAPTIC_METHOD_VIBRATE); } else { EXPECT_METHOD_NOT_CALLED_EVENTUALLY(haptic_mock, haptic_obj, HAPTIC_METHOD_VIBRATE); } // confirm that the notification was as expected guint num_notify_calls = 0; 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); if (num_notify_calls > 0) { // test that Notify was called with the app_name const gchar* app_name {nullptr}; g_variant_get_child(notify_calls[0].params, 0, "&s", &app_name); ASSERT_STREQ(APP_NAME, app_name); // test that Notify was called with the type-appropriate icon const gchar* icon_name {nullptr}; g_variant_get_child(notify_calls[0].params, 2, "&s", &icon_name); ASSERT_STREQ(test_appt.icon_name, icon_name); // test that the Notification title has the correct prefix const gchar* title {nullptr}; g_variant_get_child(notify_calls[0].params, 3, "&s", &title); ASSERT_TRUE(g_str_has_prefix(title, test_appt.prefix)); // test that Notify was called with the appointment's body const gchar* body {nullptr}; g_variant_get_child(notify_calls[0].params, 4, "&s", &body); ASSERT_STREQ(test_appt.appt.summary.c_str(), body); } } } } } }