From 8910c3c25d9c3c77aaa987fdc366cd77f63d376c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 21 Jan 2014 23:27:45 -0600 Subject: Extract the MockState logic from state-fixture.h so that it can be reused for testing LiveActions --- tests/state-mock.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/state-mock.h (limited to 'tests/state-mock.h') diff --git a/tests/state-mock.h b/tests/state-mock.h new file mode 100644 index 0000000..ae1217b --- /dev/null +++ b/tests/state-mock.h @@ -0,0 +1,49 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace unity::indicator::datetime; + +class MockState: public State +{ +public: + std::shared_ptr mock_clock; + + MockState() + { + const DateTime now = DateTime::NowLocal(); + mock_clock.reset(new MockClock(now)); + settings.reset(new Settings); + timezones.reset(new Timezones); + clock = std::dynamic_pointer_cast(mock_clock); + planner.reset(new MockPlanner); + planner->time = now; + locations.reset(new Locations); + calendar_day = now; + } +}; + -- cgit v1.2.3 From 931e448b916453139e2c043161088851a1b47b42 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 00:33:22 -0600 Subject: remove unnecessary #includes --- tests/state-mock.h | 3 --- tests/test-menus.cc | 4 ---- 2 files changed, 7 deletions(-) (limited to 'tests/state-mock.h') diff --git a/tests/state-mock.h b/tests/state-mock.h index ae1217b..2104aa0 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -18,11 +18,8 @@ */ #include -#include #include -#include #include -#include #include #include diff --git a/tests/test-menus.cc b/tests/test-menus.cc index 95ac5c2..fe1e86e 100644 --- a/tests/test-menus.cc +++ b/tests/test-menus.cc @@ -22,13 +22,9 @@ #include "state-fixture.h" #include -#include #include #include -#include -#include #include -#include #include -- cgit v1.2.3 From 2db8f6e7c4b7148377800400c72bb2e59b793d3a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 10:01:20 -0600 Subject: remove the State.timezones property. Timezones is a helper class for LiveClock and doesn't need to be public in State. --- include/datetime/state.h | 11 ++++++++++- src/state-live.cpp | 1 - tests/state-mock.h | 3 --- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'tests/state-mock.h') diff --git a/include/datetime/state.h b/include/datetime/state.h index e735b6f..b14908e 100644 --- a/include/datetime/state.h +++ b/include/datetime/state.h @@ -52,11 +52,20 @@ namespace datetime { */ struct State { + /** \brief The current time. Used by the header, by the date menuitem, + and by the locations for relative timestamp */ std::shared_ptr clock; + + /** \brief The locations to be displayed in the Locations + section of the #Menu */ std::shared_ptr locations; + + /** \brief The appointments to be displayed in the Calendar and + Appointments sections of the #Menu */ std::shared_ptr planner; + + /** \brief Configuration options that modify the view */ std::shared_ptr settings; - std::shared_ptr timezones; core::Property calendar_day; }; diff --git a/src/state-live.cpp b/src/state-live.cpp index f4690b3..8ee663b 100644 --- a/src/state-live.cpp +++ b/src/state-live.cpp @@ -41,7 +41,6 @@ LiveState::LiveState() std::shared_ptr live_clock(new LiveClock(live_timezones)); settings = live_settings; - timezones = live_timezones; clock = live_clock; locations.reset(new SettingsLocations(live_settings, live_timezones)); planner.reset(new PlannerEds); diff --git a/tests/state-mock.h b/tests/state-mock.h index 2104aa0..f2e58e6 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -18,10 +18,8 @@ */ #include -#include #include #include -#include using namespace unity::indicator::datetime; @@ -35,7 +33,6 @@ public: const DateTime now = DateTime::NowLocal(); mock_clock.reset(new MockClock(now)); settings.reset(new Settings); - timezones.reset(new Timezones); clock = std::dynamic_pointer_cast(mock_clock); planner.reset(new MockPlanner); planner->time = now; -- cgit v1.2.3 From 08b1cfd6bc97cae18b916d97a03781986e7421fe Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 10:15:56 -0600 Subject: move planner-mock.h from include/datetime/ to tests/ because it's only needed by the tests. --- include/datetime/planner-mock.h | 44 ---------------------------------- tests/planner-mock.h | 52 +++++++++++++++-------------------------- tests/state-mock.h | 3 ++- 3 files changed, 21 insertions(+), 78 deletions(-) delete mode 100644 include/datetime/planner-mock.h (limited to 'tests/state-mock.h') diff --git a/include/datetime/planner-mock.h b/include/datetime/planner-mock.h deleted file mode 100644 index 44d30c7..0000000 --- a/include/datetime/planner-mock.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * 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 - */ - -#ifndef INDICATOR_DATETIME_PLANNER_MOCK_H -#define INDICATOR_DATETIME_PLANNER_MOCK_H - -#include - -namespace unity { -namespace indicator { -namespace datetime { - -/** - * \brief Planner which does nothing on its own. - * It requires its client must set its appointments property. - */ -class MockPlanner: public Planner -{ -public: - MockPlanner() =default; - virtual ~MockPlanner() =default; -}; - -} // namespace datetime -} // namespace indicator -} // namespace unity - -#endif // INDICATOR_DATETIME_PLANNER_MOCK_H diff --git a/tests/planner-mock.h b/tests/planner-mock.h index 8d7d7c2..44d30c7 100644 --- a/tests/planner-mock.h +++ b/tests/planner-mock.h @@ -1,9 +1,6 @@ /* * Copyright 2013 Canonical Ltd. * - * Authors: - * Charles Kerr - * * 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. @@ -15,44 +12,33 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ -#ifndef __INDICATOR_DATETIME_PLANNER_MOCK__H__ -#define __INDICATOR_DATETIME_PLANNER_MOCK__H__ - -#include "planner.h" /* parent class */ +#ifndef INDICATOR_DATETIME_PLANNER_MOCK_H +#define INDICATOR_DATETIME_PLANNER_MOCK_H -G_BEGIN_DECLS +#include -#define INDICATOR_TYPE_DATETIME_PLANNER_MOCK (indicator_datetime_planner_mock_get_type()) -#define INDICATOR_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMock)) -#define INDICATOR_DATETIME_PLANNER_MOCK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMockClass)) -#define INDICATOR_IS_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK)) - -typedef struct _IndicatorDatetimePlannerMock IndicatorDatetimePlannerMock; -typedef struct _IndicatorDatetimePlannerMockPriv IndicatorDatetimePlannerMockPriv; -typedef struct _IndicatorDatetimePlannerMockClass IndicatorDatetimePlannerMockClass; - -GType indicator_datetime_planner_mock_get_type (void); +namespace unity { +namespace indicator { +namespace datetime { /** - * An IndicatorDatetimePlanner which uses Evolution Data Server - * to get its list of appointments. + * \brief Planner which does nothing on its own. + * It requires its client must set its appointments property. */ -struct _IndicatorDatetimePlannerMock -{ - /*< private >*/ - IndicatorDatetimePlanner parent; - IndicatorDatetimePlannerMockPriv * priv; -}; - -struct _IndicatorDatetimePlannerMockClass +class MockPlanner: public Planner { - IndicatorDatetimePlannerClass parent_class; +public: + MockPlanner() =default; + virtual ~MockPlanner() =default; }; -IndicatorDatetimePlanner * indicator_datetime_planner_mock_new (void); - -G_END_DECLS +} // namespace datetime +} // namespace indicator +} // namespace unity -#endif /* __INDICATOR_DATETIME_PLANNER_MOCK__H__ */ +#endif // INDICATOR_DATETIME_PLANNER_MOCK_H diff --git a/tests/state-mock.h b/tests/state-mock.h index f2e58e6..64ab08b 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -17,8 +17,9 @@ * Charles Kerr */ +#include "planner-mock.h" + #include -#include #include using namespace unity::indicator::datetime; -- cgit v1.2.3 From 7b09a0ff5652bdca7c8d8e046d2af6a696f94147 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 25 Jan 2014 16:54:41 -0600 Subject: sync the exported calendar state with the #State backend --- include/datetime/actions.h | 4 +- include/datetime/state.h | 2 - src/actions-live.cpp | 5 -- src/actions.cpp | 30 +++++++++++- src/state-live.cpp | 1 - tests/actions-mock.h | 8 +--- tests/state-mock.h | 1 - tests/test-actions.cpp | 19 +++++--- tests/test-live-actions.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 157 insertions(+), 27 deletions(-) (limited to 'tests/state-mock.h') diff --git a/include/datetime/actions.h b/include/datetime/actions.h index 18286dc..3686b95 100644 --- a/include/datetime/actions.h +++ b/include/datetime/actions.h @@ -49,8 +49,7 @@ public: virtual void open_planner_at(const DateTime&) =0; virtual void open_appointment(const std::string& uid) =0; virtual void set_location(const std::string& zone, const std::string& name)=0; - virtual void set_calendar_date(const DateTime&) =0; - + void set_calendar_date(const DateTime&); GActionGroup* action_group() { return G_ACTION_GROUP(m_actions); } std::shared_ptr state() { return m_state; } @@ -61,6 +60,7 @@ protected: private: std::shared_ptr m_state; GSimpleActionGroup* m_actions = nullptr; + void update_calendar_state(); // we've got raw pointers in here, so disable copying Actions(const Actions&) =delete; diff --git a/include/datetime/state.h b/include/datetime/state.h index b14908e..414be32 100644 --- a/include/datetime/state.h +++ b/include/datetime/state.h @@ -66,8 +66,6 @@ struct State /** \brief Configuration options that modify the view */ std::shared_ptr settings; - - core::Property calendar_day; }; } // namespace datetime diff --git a/src/actions-live.cpp b/src/actions-live.cpp index e4f5e9f..d5f7180 100644 --- a/src/actions-live.cpp +++ b/src/actions-live.cpp @@ -96,11 +96,6 @@ void LiveActions::open_appointment(const std::string& uid) } } -void LiveActions::set_calendar_date(const DateTime& dt) -{ - state()->calendar_day.set(dt); -} - /*** **** ***/ diff --git a/src/actions.cpp b/src/actions.cpp index 1d80c99..a6a7c0b 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -150,7 +150,7 @@ GVariant* create_calendar_state(const std::shared_ptr& state) g_variant_builder_add(&dict_builder, "{sv}", key, v); key = "calendar-day"; - v = g_variant_new_int64(state->calendar_day.get().to_unix()); + v = g_variant_new_int64(state->planner->time.get().to_unix()); g_variant_builder_add(&dict_builder, "{sv}", key, v); key = "show-week-numbers"; @@ -200,7 +200,20 @@ Actions::Actions(const std::shared_ptr& state): a = g_simple_action_new_stateful("calendar", G_VARIANT_TYPE_INT64, v); g_action_map_add_action(gam, G_ACTION(a)); g_signal_connect(a, "activate", G_CALLBACK(on_calendar_activated), this); - //m_calendar_action = a; + + /// + /// Keep our GActionGroup's action's states in sync with m_state + /// + + m_state->planner->time.changed().connect([this](const DateTime&){ + update_calendar_state(); + }); + m_state->planner->thisMonth.changed().connect([this](const std::vector&){ + update_calendar_state(); + }); + m_state->settings->show_week_numbers.changed().connect([this](bool){ + update_calendar_state(); + }); // FIXME: rebuild the calendar state when show-week-number changes } @@ -210,6 +223,19 @@ Actions::~Actions() g_clear_object(&m_actions); } +void Actions::update_calendar_state() +{ + g_action_group_change_action_state(action_group(), + "calendar", + create_calendar_state(m_state)); +} + +void Actions::set_calendar_date(const DateTime& date) +{ + m_state->planner->time.set(date); +} + + } // namespace datetime } // namespace indicator } // namespace unity diff --git a/src/state-live.cpp b/src/state-live.cpp index 8ee663b..fe1e6cd 100644 --- a/src/state-live.cpp +++ b/src/state-live.cpp @@ -45,7 +45,6 @@ LiveState::LiveState() locations.reset(new SettingsLocations(live_settings, live_timezones)); planner.reset(new PlannerEds); planner->time = clock->localtime(); - calendar_day = clock->localtime(); } /*** diff --git a/tests/actions-mock.h b/tests/actions-mock.h index 112900b..da93cb9 100644 --- a/tests/actions-mock.h +++ b/tests/actions-mock.h @@ -35,8 +35,7 @@ public: ~MockActions() =default; enum Action { OpenDesktopSettings, OpenPhoneSettings, OpenPhoneClockApp, - OpenPlanner, OpenPlannerAt, OpenAppointment, - SetLocation, SetCalendarDate }; + OpenPlanner, OpenPlannerAt, OpenAppointment, SetLocation }; const std::vector& history() const { return m_history; } const DateTime& date_time() const { return m_date_time; } const std::string& zone() const { return m_zone; } @@ -68,11 +67,6 @@ public: m_url = url_; } - void set_calendar_date(const DateTime& date_time_) { - m_history.push_back(SetCalendarDate); - m_date_time = date_time_; - } - private: std::string m_url; std::string m_zone; diff --git a/tests/state-mock.h b/tests/state-mock.h index 64ab08b..721b82f 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -38,7 +38,6 @@ public: planner.reset(new MockPlanner); planner->time = now; locations.reset(new Locations); - calendar_day = now; } }; diff --git a/tests/test-actions.cpp b/tests/test-actions.cpp index 4329608..c30d1fb 100644 --- a/tests/test-actions.cpp +++ b/tests/test-actions.cpp @@ -137,18 +137,23 @@ TEST_F(ActionsFixture, SetLocation) TEST_F(ActionsFixture, 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)); - auto unix = m_state->clock->localtime().to_unix(); - auto v = g_variant_new_int64(unix); - g_action_group_activate_action(action_group, action_name, v); - const auto expected_action = MockActions::SetCalendarDate; - ASSERT_EQ(1, m_mock_actions->history().size()); - EXPECT_EQ(expected_action, m_mock_actions->history()[0]); - EXPECT_EQ(unix, m_mock_actions->date_time().to_unix()); + // pick an arbitrary DateTime... + auto tmp = g_date_time_new_local(2010, 1, 2, 3, 4, 5); + const auto now = DateTime(tmp); + g_date_time_unref(tmp); + + // 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->planner->time.get()); + auto v = g_variant_new_int64(now.to_unix()); + g_action_group_activate_action (action_group, action_name, v); + EXPECT_EQ (now, m_state->planner->time.get()); } TEST_F(ActionsFixture, OpenAppointment) diff --git a/tests/test-live-actions.cpp b/tests/test-live-actions.cpp index d3d7720..562b358 100644 --- a/tests/test-live-actions.cpp +++ b/tests/test-live-actions.cpp @@ -287,3 +287,117 @@ TEST_F(LiveActionsFixture, OpenPlannerAt) const std::string expected = now.format("evolution \"calendar:///?startdate=%Y%m%d\""); EXPECT_EQ(expected, m_live_actions->last_cmd); } + +TEST_F(LiveActionsFixture, CalendarState) +{ + // init the clock + auto tmp = g_date_time_new_local (2014, 1, 1, 0, 0, 0); + const DateTime now (tmp); + g_date_time_unref (tmp); + m_mock_state->mock_clock->set_localtime (now); + m_state->planner->time.set(now); + + /// + /// Test the default calendar state. + /// + + auto action_group = m_actions->action_group(); + 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)); + + // there's nothing in the planner yet, so appointment-days should be an empty array + auto v = g_variant_lookup_value (calendar_state, "appointment-days", G_VARIANT_TYPE_ARRAY); + EXPECT_TRUE (v != nullptr); + EXPECT_EQ (0, g_variant_n_children (v)); + g_clear_pointer (&v, g_variant_unref); + + // calendar-day should be in sync with m_state->calendar_day + v = g_variant_lookup_value (calendar_state, "calendar-day", G_VARIANT_TYPE_INT64); + EXPECT_TRUE (v != nullptr); + EXPECT_EQ (m_state->planner->time.get().to_unix(), g_variant_get_int64(v)); + g_clear_pointer (&v, g_variant_unref); + + // show-week-numbers should be false because MockSettings defaults everything to 0 + v = g_variant_lookup_value (calendar_state, "show-week-numbers", G_VARIANT_TYPE_BOOLEAN); + EXPECT_TRUE (v != nullptr); + EXPECT_FALSE (g_variant_get_boolean (v)); + g_clear_pointer (&v, g_variant_unref); + + // cleanup this step + g_clear_pointer (&calendar_state, g_variant_unref); + + + /// + /// Now add appointments to the planner and confirm that the state keeps in sync + /// + + auto tomorrow = g_date_time_add_days (now.get(), 1); + auto tomorrow_begin = g_date_time_add_full (tomorrow, 0, 0, 0, + -g_date_time_get_hour(tomorrow), + -g_date_time_get_minute(tomorrow), + -g_date_time_get_seconds(tomorrow)); + auto tomorrow_end = g_date_time_add_full (tomorrow_begin, 0, 0, 1, 0, 0, -1); + Appointment a1; + a1.color = "green"; + a1.summary = "write unit tests"; + a1.url = "http://www.ubuntu.com/"; + a1.uid = "D4B57D50247291478ED31DED17FF0A9838DED402"; + a1.begin = tomorrow_begin; + a1.end = tomorrow_end; + + auto next_begin = g_date_time_add_days (tomorrow_begin, 1); + auto next_end = g_date_time_add_full (next_begin, 0, 0, 1, 0, 0, -1); + Appointment a2; + a2.color = "orange"; + a2.summary = "code review"; + a2.url = "http://www.ubuntu.com/"; + a2.uid = "2756ff7de3745bbffd65d2e4779c37c7ca60d843"; + a2.begin = next_begin; + a2.end = next_end; + + m_state->planner->thisMonth.set(std::vector({a1, a2})); + + /// + /// Now test the calendar state again. + /// The thisMonth field should now contain the appointments we just added. + /// + + calendar_state = g_action_group_get_action_state (action_group, "calendar"); + v = g_variant_lookup_value (calendar_state, "appointment-days", G_VARIANT_TYPE_ARRAY); + EXPECT_TRUE (v != nullptr); + int i; + g_variant_get_child (v, 0, "i", &i); + EXPECT_EQ (g_date_time_get_day_of_month(a1.begin.get()), i); + g_variant_get_child (v, 1, "i", &i); + EXPECT_EQ (g_date_time_get_day_of_month(a2.begin.get()), i); + g_clear_pointer(&v, g_variant_unref); + g_clear_pointer(&calendar_state, g_variant_unref); + + // cleanup this step + g_date_time_unref (next_end); + g_date_time_unref (next_begin); + g_date_time_unref (tomorrow_end); + g_date_time_unref (tomorrow_begin); + g_date_time_unref (tomorrow); + + /// + /// Confirm that the action state's dictionary + /// keeps in sync with settings.show_week_numbers + /// + + auto b = m_state->settings->show_week_numbers.get(); + for (i=0; i<2; i++) + { + b = !b; + m_state->settings->show_week_numbers.set(b); + + calendar_state = g_action_group_get_action_state (action_group, "calendar"); + v = g_variant_lookup_value (calendar_state, "show-week-numbers", G_VARIANT_TYPE_BOOLEAN); + EXPECT_TRUE(v != nullptr); + EXPECT_EQ(b, g_variant_get_boolean(v)); + + g_clear_pointer(&v, g_variant_unref); + g_clear_pointer(&calendar_state, g_variant_unref); + } +} -- cgit v1.2.3