// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/time/calendar_view_controller.h"
#include <memory>
#include <string>
#include <utility>
#include "ash/system/time/calendar_utils.h"
#include "ash/test/ash_test_base.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "chromeos/ash/components/settings/scoped_timezone_settings.h"
namespace ash {
using CalendarViewControllerUnittest = AshTestBase;
TEST_F(CalendarViewControllerUnittest, UtilFunctions) {
auto controller = std::make_unique<CalendarViewController>();
base::Time date;
ASSERT_TRUE(base::Time::FromString("24 Aug 2021 10:00 GMT", &date));
controller->UpdateMonth(date);
base::Time::Exploded first_day_exploded;
base::Time first_day = controller->GetOnScreenMonthFirstDayUTC();
first_day.LocalExplode(&first_day_exploded);
std::u16string month_name = controller->GetOnScreenMonthName();
EXPECT_EQ(8, first_day_exploded.month);
EXPECT_EQ(1, first_day_exploded.day_of_month);
EXPECT_EQ(2021, first_day_exploded.year);
EXPECT_EQ(u"August", month_name);
base::Time::Exploded previous_first_day_exploded;
base::Time previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_first_day.LocalExplode(&previous_first_day_exploded);
std::u16string previous_month_name = controller->GetPreviousMonthName();
EXPECT_EQ(7, previous_first_day_exploded.month);
EXPECT_EQ(1, previous_first_day_exploded.day_of_month);
EXPECT_EQ(2021, previous_first_day_exploded.year);
EXPECT_EQ(u"July", previous_month_name);
base::Time::Exploded next_first_day_exploded;
base::Time next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_first_day.LocalExplode(&next_first_day_exploded);
std::u16string next_month_name = controller->GetNextMonthName();
EXPECT_EQ(9, next_first_day_exploded.month);
EXPECT_EQ(1, next_first_day_exploded.day_of_month);
EXPECT_EQ(2021, next_first_day_exploded.year);
EXPECT_EQ(u"September", next_month_name);
}
TEST_F(CalendarViewControllerUnittest, CornerCases) {
auto controller = std::make_unique<CalendarViewController>();
// Next month of Dec should be Jan of next year.
base::Time last_month_date;
ASSERT_TRUE(
base::Time::FromString("24 Dec 2021 10:00 GMT", &last_month_date));
controller->UpdateMonth(last_month_date);
base::Time::Exploded january_first_day_exploded;
base::Time january_first_day = controller->GetNextMonthFirstDayUTC(1);
january_first_day.LocalExplode(&january_first_day_exploded);
std::u16string january_month_name = controller->GetNextMonthName();
EXPECT_EQ(1, january_first_day_exploded.month);
EXPECT_EQ(1, january_first_day_exploded.day_of_month);
EXPECT_EQ(2022, january_first_day_exploded.year);
EXPECT_EQ(u"January", january_month_name);
// Previous month of Jan should be Dec of last year
base::Time first_month_date;
ASSERT_TRUE(
base::Time::FromString("24 Jan 2021 10:00 GMT", &first_month_date));
controller->UpdateMonth(first_month_date);
base::Time::Exploded dec_first_day_exploded;
base::Time dec_first_day = controller->GetPreviousMonthFirstDayUTC(1);
dec_first_day.LocalExplode(&dec_first_day_exploded);
std::u16string dec_month_name = controller->GetPreviousMonthName();
EXPECT_EQ(12, dec_first_day_exploded.month);
EXPECT_EQ(1, dec_first_day_exploded.day_of_month);
EXPECT_EQ(2020, dec_first_day_exploded.year);
EXPECT_EQ(u"December", dec_month_name);
}
// Tests the date function can return the correct date when DST starts/ends.
TEST_F(CalendarViewControllerUnittest, GetDatesWithDaylightSaving) {
auto controller = std::make_unique<CalendarViewController>();
// Set the timezone to GMT.
ash::system::ScopedTimezoneSettings timezone_settings(u"GMT");
// Set current month to 4/1/2022 00:00 PST, which is 4/1/2022 07:00 GMT.
base::Time current_month_date;
ASSERT_TRUE(
base::Time::FromString("1 Apr 2022 00:00 PST", ¤t_month_date));
controller->UpdateMonth(current_month_date);
base::Time previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
std::u16string previous_month_name = controller->GetPreviousMonthName();
base::Time next_first_day = controller->GetNextMonthFirstDayUTC(1);
std::u16string next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"March 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"March", previous_month_name);
EXPECT_EQ(u"May 1, 2022", calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"May", next_month_name);
// Set timezone to Pacific Daylight Time. Mar 13th is the daylight saving
// starts day.
timezone_settings.SetTimezoneFromID(u"PST");
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"March 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"March", previous_month_name);
EXPECT_EQ(u"May 1, 2022", calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"May", next_month_name);
// Set current month to 4/1/2022 00:00 GMT, which should be 3/31/2022 17:00
// PST.
base::Time current_month_date2;
ASSERT_TRUE(
base::Time::FromString("1 Apr 2022 00:00 GMT", ¤t_month_date2));
controller->UpdateMonth(current_month_date2);
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"February 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"February", previous_month_name);
EXPECT_EQ(u"April 1, 2022", calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"April", next_month_name);
// Set the timezone back to GMT.
timezone_settings.SetTimezoneFromID(u"GMT");
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"March 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"March", previous_month_name);
EXPECT_EQ(u"May 1, 2022", calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"May", next_month_name);
// Set current month to 11/1/2022 00:00 PST, which is 11/1/2022 07:00 GMT.
base::Time current_month_date3;
ASSERT_TRUE(
base::Time::FromString("1 Nov 2022 00:00 PST", ¤t_month_date3));
controller->UpdateMonth(current_month_date3);
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"October 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"October", previous_month_name);
EXPECT_EQ(u"December 1, 2022",
calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"December", next_month_name);
// Set timezone to Pacific Daylight Time. Nov 6th is the daylight saving
// ends day.
timezone_settings.SetTimezoneFromID(u"PST");
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"October 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"October", previous_month_name);
EXPECT_EQ(u"December 1, 2022",
calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"December", next_month_name);
// Set current month to 11/1/2022 00:00 GMT, which should be 10/31/2022 17:00
// PST.
base::Time current_month_date4;
ASSERT_TRUE(
base::Time::FromString("1 Nov 2022 00:00 GMT", ¤t_month_date4));
controller->UpdateMonth(current_month_date4);
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"September 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"September", previous_month_name);
EXPECT_EQ(u"November 1, 2022",
calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"November", next_month_name);
// Set the timezone back to GMT.
timezone_settings.SetTimezoneFromID(u"GMT");
previous_first_day = controller->GetPreviousMonthFirstDayUTC(1);
previous_month_name = controller->GetPreviousMonthName();
next_first_day = controller->GetNextMonthFirstDayUTC(1);
next_month_name = controller->GetNextMonthName();
EXPECT_EQ(u"October 1, 2022",
calendar_utils::GetMonthDayYear(previous_first_day));
EXPECT_EQ(u"October", previous_month_name);
EXPECT_EQ(u"December 1, 2022",
calendar_utils::GetMonthDayYear(next_first_day));
EXPECT_EQ(u"December", next_month_name);
}
// Tests that Ash.Calendar.MaxDistanceBrowsed records once on destruction of
// CalendarViewController.
TEST_F(CalendarViewControllerUnittest, MaxDistanceBrowsedRecordedOnClose) {
base::HistogramTester histogram_tester;
auto controller = std::make_unique<CalendarViewController>();
histogram_tester.ExpectTotalCount("Ash.Calendar.MaxDistanceBrowsed", 0);
// Destroy the controller (this happens when the calendar is closed). The
// metric should be recorded once.
controller.reset();
histogram_tester.ExpectTotalCount("Ash.Calendar.MaxDistanceBrowsed", 1);
}
TEST_F(
CalendarViewControllerUnittest,
ShouldRecordEventListViewJoinMeetingButtonPressed_WhenEventListIsShowing) {
base::HistogramTester histogram_tester;
auto controller = std::make_unique<CalendarViewController>();
controller->OnEventListOpened();
const std::unique_ptr<ui::Event> test_event = std::make_unique<ui::KeyEvent>(
ui::EventType::kMousePressed, ui::VKEY_UNKNOWN, ui::EF_NONE);
controller->RecordJoinMeetingButtonPressed(*test_event);
histogram_tester.ExpectTotalCount(
"Ash.Calendar.EventListView.JoinMeetingButton.Pressed", 1);
}
TEST_F(
CalendarViewControllerUnittest,
ShouldRecordUpNextViewJoinMeetingButtonPressed_WhenEventListIsNotShowing) {
base::HistogramTester histogram_tester;
auto controller = std::make_unique<CalendarViewController>();
const std::unique_ptr<ui::Event> test_event = std::make_unique<ui::KeyEvent>(
ui::EventType::kMousePressed, ui::VKEY_UNKNOWN, ui::EF_NONE);
controller->RecordJoinMeetingButtonPressed(*test_event);
histogram_tester.ExpectTotalCount(
"Ash.Calendar.UpNextView.JoinMeetingButton.Pressed", 1);
}
} // namespace ash