/* * Copyright 2013 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 "state-fixture.h" using namespace ayatana::indicator::datetime; class ActionsFixture: public StateFixture { typedef StateFixture super; std::vector build_some_appointments() { const auto now = m_state->clock->localtime(); const auto tomorrow = now.add_days(1); Appointment a1; // an alarm clock appointment a1.color = "red"; a1.summary = "http://www.example.com/"; a1.uid = "example"; a1.type = Appointment::ALARM; a1.begin = a1.end = tomorrow; Appointment a2; // a non-alarm appointment a2.color = "green"; a2.summary = "http://www.monkey.com/"; a2.uid = "monkey"; a2.type = Appointment::EVENT; a2.begin = a2.end = tomorrow; return std::vector({a1, a2}); } protected: void SetUp() override { super::SetUp(); } void TearDown() override { super::TearDown(); } void test_action_with_no_args(const char * action_name, MockActions::Action expected_action) { // preconditions EXPECT_TRUE(m_mock_actions->history().empty()); auto action_group = m_actions->action_group(); EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); // run the test g_action_group_activate_action(action_group, action_name, nullptr); // test the results EXPECT_EQ(std::vector({expected_action}), m_mock_actions->history()); } void test_action_with_time_arg(const char * action_name, MockActions::Action expected_action) { // preconditions EXPECT_TRUE(m_mock_actions->history().empty()); auto action_group = m_actions->action_group(); EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); // activate the action const auto now = DateTime::NowLocal(); auto v = g_variant_new_int64(now.to_unix()); g_action_group_activate_action(action_group, action_name, v); // test the results EXPECT_EQ(std::vector({expected_action}), m_mock_actions->history()); EXPECT_EQ(now.format("%F %T"), m_mock_actions->date_time().format("%F %T")); } void test_action_with_appt_arg(const char * action_name, MockActions::Action expected_action) { /// /// Test 1: activate an appointment that we know about /// // preconditions EXPECT_TRUE(m_mock_actions->history().empty()); auto action_group = m_actions->action_group(); EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); // init some appointments to the state const auto appointments = build_some_appointments(); m_mock_state->mock_range_planner->appointments().set(appointments); // activate the action auto v = g_variant_new("(sx)", appointments[0].uid.c_str(), 0); g_action_group_activate_action(action_group, action_name, v); // test the results EXPECT_EQ(std::vector({expected_action}), m_mock_actions->history()); EXPECT_EQ(appointments[0], m_mock_actions->appointment()); /// /// Test 2: activate an appointment we *don't* know about /// // setup m_mock_actions->clear(); EXPECT_TRUE(m_mock_actions->history().empty()); // activate the action v = g_variant_new("(sx)", "this-uid-is-not-one-that-we-have", 0); g_action_group_activate_action(action_group, action_name, v); // test the results EXPECT_TRUE(m_mock_actions->history().empty()); } }; /*** **** ***/ TEST_F(ActionsFixture, ActionsExist) { EXPECT_TRUE(m_actions != nullptr); const char* names[] = { "desktop-header", "calendar", "set-location", "desktop.open-appointment", "desktop.open-alarm-app", "desktop.open-calendar-app", "desktop.open-settings-app", "phone.open-appointment", "phone.open-alarm-app", "phone.open-calendar-app", "phone.open-settings-app" }; for(const auto& name: names) { EXPECT_TRUE(g_action_group_has_action(m_actions->action_group(), name)); } } /*** **** ***/ TEST_F(ActionsFixture, DesktopOpenAlarmApp) { test_action_with_no_args("desktop.open-alarm-app", MockActions::OpenAlarmApp); } TEST_F(ActionsFixture, DesktopOpenAppointment) { test_action_with_appt_arg("desktop.open-appointment", MockActions::OpenAppt); } TEST_F(ActionsFixture, DesktopOpenCalendarApp) { test_action_with_time_arg("desktop.open-calendar-app", MockActions::OpenCalendarApp); } TEST_F(ActionsFixture, DesktopOpenSettingsApp) { test_action_with_no_args("desktop.open-settings-app", MockActions::OpenSettingsApp); } /*** **** ***/ TEST_F(ActionsFixture, PhoneOpenAlarmApp) { test_action_with_no_args("phone.open-alarm-app", MockActions::OpenAlarmApp); } TEST_F(ActionsFixture, PhoneOpenAppointment) { test_action_with_appt_arg("phone.open-appointment", MockActions::OpenAppt); } TEST_F(ActionsFixture, PhoneOpenCalendarApp) { test_action_with_time_arg("phone.open-calendar-app", MockActions::OpenCalendarApp); } TEST_F(ActionsFixture, PhoneOpenSettingsApp) { test_action_with_no_args("phone.open-settings-app", MockActions::OpenSettingsApp); } /*** **** ***/ TEST_F(ActionsFixture, SetLocation) { const auto action_name = "set-location"; auto action_group = m_actions->action_group(); EXPECT_TRUE(m_mock_actions->history().empty()); EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); auto v = g_variant_new_string("America/Chicago Oklahoma City"); g_action_group_activate_action(action_group, action_name, v); const auto expected_action = MockActions::SetLocation; ASSERT_EQ(1, m_mock_actions->history().size()); EXPECT_EQ(expected_action, m_mock_actions->history()[0]); EXPECT_EQ("America/Chicago", m_mock_actions->zone()); EXPECT_EQ("Oklahoma City", m_mock_actions->name()); } TEST_F(ActionsFixture, DISABLED_SetCalendarDate) { // confirm that such an action exists const auto action_name = "calendar"; auto action_group = m_actions->action_group(); EXPECT_TRUE(m_mock_actions->history().empty()); EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); // pick an arbitrary DateTime... auto now = DateTime::Local(2010, 1, 2, 3, 4, 5); // confirm that Planner.time gets changed to that date when we // activate the 'calendar' action with that date's time_t as the arg EXPECT_NE (now, m_state->calendar_month->month().get()); auto v = g_variant_new_int64(now.to_unix()); g_action_group_activate_action (action_group, action_name, v); EXPECT_TRUE(DateTime::is_same_day (now, m_state->calendar_month->month().get())); // DST change in US now = DateTime::Local(2015, 3, 8, 9, 0, 0); v = g_variant_new_int64(now.to_unix()); g_action_group_activate_action (action_group, action_name, v); EXPECT_TRUE(DateTime::is_same_day (now, m_state->calendar_month->month().get())); // DST change in Europe now = DateTime::Local(2015, 3, 29, 9, 0, 0); v = g_variant_new_int64(now.to_unix()); g_action_group_activate_action (action_group, action_name, v); EXPECT_TRUE(DateTime::is_same_day (now, m_state->calendar_month->month().get())); } TEST_F(ActionsFixture, DISABLED_ActivatingTheCalendarResetsItsDate) { // Confirm that the GActions exist auto action_group = m_actions->action_group(); EXPECT_TRUE(g_action_group_has_action(action_group, "calendar")); EXPECT_TRUE(g_action_group_has_action(action_group, "calendar-active")); /// /// Prerequisite for the test: move calendar-date away from today /// // move calendar-date a week into the future... const auto now = m_state->clock->localtime(); const auto next_week = now.add_days(7); const auto next_week_unix = next_week.to_unix(); g_action_group_activate_action (action_group, "calendar", g_variant_new_int64(next_week_unix)); // confirm the planner and calendar action state moved a week into the future // but that m_state->clock is unchanged auto expected = next_week.start_of_day(); const auto expected_unix = expected.to_unix(); EXPECT_EQ(expected_unix, m_state->calendar_month->month().get().to_unix()); EXPECT_EQ(now, m_state->clock->localtime()); auto calendar_state = g_action_group_get_action_state(action_group, "calendar"); EXPECT_TRUE(calendar_state != nullptr); EXPECT_TRUE(g_variant_is_of_type(calendar_state, G_VARIANT_TYPE_DICTIONARY)); auto v = g_variant_lookup_value(calendar_state, "calendar-day", G_VARIANT_TYPE_INT64); EXPECT_TRUE(v != nullptr); EXPECT_EQ(expected_unix, g_variant_get_int64(v)); g_clear_pointer(&v, g_variant_unref); g_clear_pointer(&calendar_state, g_variant_unref); /// /// Now the actual test. /// We set the state of 'calendar-active' to true, which should reset the calendar date. /// This is so the calendar always starts on today's date when the indicator's menu is pulled down. /// // change the state... g_action_group_change_action_state(action_group, "calendar-active", g_variant_new_boolean(true)); // confirm the planner and calendar action state were reset back to m_state->clock's time EXPECT_EQ(now.to_unix(), m_state->calendar_month->month().get().to_unix()); EXPECT_EQ(now, m_state->clock->localtime()); calendar_state = g_action_group_get_action_state(action_group, "calendar"); EXPECT_TRUE(calendar_state != nullptr); EXPECT_TRUE(g_variant_is_of_type(calendar_state, G_VARIANT_TYPE_DICTIONARY)); v = g_variant_lookup_value(calendar_state, "calendar-day", G_VARIANT_TYPE_INT64); EXPECT_TRUE(v != nullptr); EXPECT_EQ(now.to_unix(), g_variant_get_int64(v)); g_clear_pointer(&v, g_variant_unref); g_clear_pointer(&calendar_state, g_variant_unref); }