blob: 9ee0a3c585c292be121e843dcf7967811ab9df1d [file] [log] [blame]
// 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 "google_apis/calendar/calendar_api_requests.h"
#include <string>
#include <vector>
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "google_apis/calendar/calendar_api_response_types.h"
#include "google_apis/common/dummy_auth_service.h"
#include "google_apis/common/request_sender.h"
#include "google_apis/common/test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/test/test_shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace google_apis {
namespace calendar {
namespace {
const char kTestCalendarColorId[] = "5";
const char kTestPrimaryCalendarColorId[] = "14";
const char kTestPrimaryCalendarSummary[] = "test1@google.com";
const char kTestUserAgent[] = "test-user-agent";
}
class CalendarApiRequestsTest : public testing::Test {
public:
CalendarApiRequestsTest()
: test_shared_loader_factory_(
base::MakeRefCounted<network::TestSharedURLLoaderFactory>(
nullptr /* network_service */,
true /* is_trusted */)) {}
void SetUp() override {
request_sender_ = std::make_unique<RequestSender>(
std::make_unique<DummyAuthService>(), test_shared_loader_factory_,
task_environment_.GetMainThreadTaskRunner(), kTestUserAgent,
TRAFFIC_ANNOTATION_FOR_TESTS);
test_server_.RegisterRequestHandler(
base::BindRepeating(&CalendarApiRequestsTest::HandleDataFileRequest,
base::Unretained(this)));
ASSERT_TRUE(test_server_.Start());
url_generator_ = std::make_unique<CalendarApiUrlGenerator>();
url_generator_->SetBaseUrlForTesting(test_server_.base_url().spec());
}
void TearDown() override {
// Deleting the sender here will delete all request objects.
request_sender_.reset();
// Wait for any DeleteSoon tasks to run.
task_environment_.RunUntilIdle();
}
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::MainThreadType::IO};
net::EmbeddedTestServer test_server_;
std::unique_ptr<RequestSender> request_sender_;
std::unique_ptr<CalendarApiUrlGenerator> url_generator_;
scoped_refptr<network::TestSharedURLLoaderFactory>
test_shared_loader_factory_;
net::test_server::HttpRequest http_request_;
// Returns a mock response based on the request URL.
std::unique_ptr<net::test_server::HttpResponse> HandleDataFileRequest(
const net::test_server::HttpRequest& request) {
http_request_ = request;
if (net::test_server::ShouldHandle(http_request_,
"/calendar/v3/calendars")) {
return test_util::CreateHttpResponseFromFile(
test_util::GetTestFilePath("calendar/events.json"));
}
if (net::test_server::ShouldHandle(http_request_,
"/calendar/v3/users/me/calendarList")) {
return test_util::CreateHttpResponseFromFile(
test_util::GetTestFilePath("calendar/calendar_list.json"));
}
NOTREACHED();
}
};
// Checks that CalendarApiCalendarListRequest can generate the correct url
// and get a calendar list response.
TEST_F(CalendarApiRequestsTest, GetCalendarListRequest) {
ApiErrorCode error = OTHER_ERROR;
std::unique_ptr<CalendarList> calendars;
{
base::RunLoop run_loop;
auto request = std::make_unique<CalendarApiCalendarListRequest>(
request_sender_.get(), *url_generator_,
test_util::CreateQuitCallback(
&run_loop,
test_util::CreateCopyResultCallback(&error, &calendars)));
request_sender_->StartRequestWithAuthRetry(std::move(request));
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
EXPECT_EQ(
"/calendar/v3/users/me/calendarList"
"?maxResults=250"
"&fields=etag%2Ckind%2Citems"
"(kind%2Cid%2Csummary%2CcolorId%2Cselected%2Cprimary)",
http_request_.relative_url);
ASSERT_TRUE(calendars.get());
EXPECT_EQ("calendar#calendarList", calendars->kind());
EXPECT_EQ(kTestPrimaryCalendarSummary, calendars->items()[0]->summary());
EXPECT_EQ(kTestPrimaryCalendarColorId, calendars->items()[0]->color_id());
EXPECT_EQ(true, calendars->items()[0]->selected());
EXPECT_EQ(true, calendars->items()[0]->primary());
}
// Tests that CalendarApiEventsRequest can generate the correct url and get the
// correct event list response.
TEST_F(CalendarApiRequestsTest, GetEventListRequest) {
ApiErrorCode error = OTHER_ERROR;
std::unique_ptr<EventList> events;
base::Time start;
base::Time end;
EXPECT_TRUE(base::Time::FromString("13 Jun 2021 10:00 GMT", &start));
EXPECT_TRUE(base::Time::FromString("16 Jun 2021 10:00 GMT", &end));
{
base::RunLoop run_loop;
auto request = std::make_unique<CalendarApiEventsRequest>(
request_sender_.get(), *url_generator_,
test_util::CreateQuitCallback(
&run_loop, test_util::CreateCopyResultCallback(&error, &events)),
start, end, /*calendar_id=*/"test1@google.com",
/*calendar_color_id=*/kTestCalendarColorId);
request_sender_->StartRequestWithAuthRetry(std::move(request));
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
EXPECT_EQ(
"/calendar/v3/calendars/test1@google.com/events"
"?timeMin=2021-06-13T10%3A00%3A00.000Z"
"&timeMax=2021-06-16T10%3A00%3A00.000Z"
"&singleEvents=true"
"&maxAttendees=1"
"&maxResults=2500"
"&fields=timeZone%2Cetag%2Ckind%2Citems(id%2Ckind%"
"2Csummary%2CcolorId%2Cstatus%"
"2Cstart(date)%2Cend(date)%"
"2Cstart(dateTime)%2Cend(dateTime)%"
"2ChtmlLink%2Cattendees(responseStatus%2Cself)%2CattendeesOmitted%"
"2CconferenceData(conferenceId%2CentryPoints(entryPointType%2Curi))%"
"2Ccreator(self)%2Clocation)",
http_request_.relative_url);
ASSERT_TRUE(events.get());
EXPECT_EQ(events->time_zone(), "America/Los_Angeles");
base::Time::Exploded exploded;
events->items()[0]->start_time().date_time().LocalExplode(&exploded);
EXPECT_EQ(exploded.month, 11);
// Verifies that events containing a colorId do not have their color IDs
// replaced by calendar_color_id.
EXPECT_EQ(events->items()[0]->color_id(), "3");
EXPECT_EQ(events->items()[1]->color_id(), "3");
// Verifies that an event without a colorId in the response yields an event
// object with a color ID equal to calendar_color_id (prepended by a marker).
EXPECT_EQ(events->items()[2]->color_id(),
calendar::kInjectedColorIdPrefix + kTestCalendarColorId);
}
// Tests that CalendarApiEventsRequest can generate the correct url and get the
// correct event list response with default optional parameters.
TEST_F(CalendarApiRequestsTest,
GetEventListRequestWithDefaultOptionalParameters) {
ApiErrorCode error = OTHER_ERROR;
std::unique_ptr<EventList> events;
base::Time start;
base::Time end;
EXPECT_TRUE(base::Time::FromString("13 Jun 2021 10:00 GMT", &start));
EXPECT_TRUE(base::Time::FromString("16 Jun 2021 10:00 GMT", &end));
{
base::RunLoop run_loop;
auto request = std::make_unique<CalendarApiEventsRequest>(
request_sender_.get(), *url_generator_,
test_util::CreateQuitCallback(
&run_loop, test_util::CreateCopyResultCallback(&error, &events)),
start, end);
request_sender_->StartRequestWithAuthRetry(std::move(request));
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
EXPECT_EQ(
"/calendar/v3/calendars/primary/events"
"?timeMin=2021-06-13T10%3A00%3A00.000Z"
"&timeMax=2021-06-16T10%3A00%3A00.000Z"
"&singleEvents=true"
"&maxAttendees=1"
"&maxResults=2500"
"&fields=timeZone%2Cetag%2Ckind%2Citems(id%2Ckind%"
"2Csummary%2CcolorId%2Cstatus%"
"2Cstart(date)%2Cend(date)%"
"2Cstart(dateTime)%2Cend(dateTime)%"
"2ChtmlLink%2Cattendees(responseStatus%2Cself)%2CattendeesOmitted%"
"2CconferenceData(conferenceId%2CentryPoints(entryPointType%2Curi))%"
"2Ccreator(self)%2Clocation)",
http_request_.relative_url);
ASSERT_TRUE(events.get());
EXPECT_EQ(events->time_zone(), "America/Los_Angeles");
base::Time::Exploded exploded;
events->items()[0]->start_time().date_time().LocalExplode(&exploded);
EXPECT_EQ(exploded.month, 11);
EXPECT_EQ(events->items()[0]->color_id(), "3");
EXPECT_EQ(events->items()[1]->color_id(), "3");
// Verifies that an event without a colorId in the response yields an event
// object with an empty colorId if no calendar_color_id is passed.
EXPECT_EQ(events->items()[2]->color_id(), "");
}
// Tests that CalendarApiEventsRequest can generate the correct url and get the
// correct event list response with extra parameters and attachments.
TEST_F(CalendarApiRequestsTest,
GetEventListRequestWithExtraParametersAndAttachments) {
ApiErrorCode error = OTHER_ERROR;
std::unique_ptr<EventList> events;
base::Time start;
base::Time end;
EXPECT_TRUE(base::Time::FromString("13 Jun 2021 10:00 GMT", &start));
EXPECT_TRUE(base::Time::FromString("16 Jun 2021 10:00 GMT", &end));
{
base::RunLoop run_loop;
std::vector<EventType> event_types;
event_types.push_back(EventType::kDefault);
auto request = std::make_unique<CalendarApiEventsRequest>(
request_sender_.get(), *url_generator_,
test_util::CreateQuitCallback(
&run_loop, test_util::CreateCopyResultCallback(&error, &events)),
start, end, event_types,
/*experiment=*/"test",
/*order_by=*/"startTime",
/*attachments=*/true);
request_sender_->StartRequestWithAuthRetry(std::move(request));
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
EXPECT_EQ(
"/calendar/v3/calendars/primary/events"
"?timeMin=2021-06-13T10%3A00%3A00.000Z"
"&timeMax=2021-06-16T10%3A00%3A00.000Z"
"&singleEvents=true"
"&maxResults=2500"
"&orderBy=startTime"
"&eventTypes=default"
"&experiment=test"
"&fields=timeZone%2Cetag%2Ckind%2Citems(id%2Ckind%"
"2Csummary%2CcolorId%2Cstatus%"
"2Cstart(date)%2Cend(date)%"
"2Cstart(dateTime)%2Cend(dateTime)%"
"2ChtmlLink%2Cattendees(responseStatus%2Cself)%2CattendeesOmitted%"
"2CconferenceData(conferenceId%2CentryPoints(entryPointType%2Curi))%"
"2Ccreator(self)%2Clocation%"
"2Cattachments(title%2CfileUrl%2CiconLink%2CfileId))",
http_request_.relative_url);
ASSERT_TRUE(events.get());
EXPECT_EQ(events->time_zone(), "America/Los_Angeles");
base::Time::Exploded exploded;
events->items()[0]->start_time().date_time().LocalExplode(&exploded);
EXPECT_EQ(exploded.month, 11);
EXPECT_EQ(events->items()[0]->color_id(), "3");
EXPECT_EQ(events->items()[1]->color_id(), "3");
// Verifies that an event without a colorId in the response yields an event
// object with an empty colorId if no calendar_color_id is passed.
EXPECT_EQ(events->items()[2]->color_id(), "");
}
// Tests that CalendarApiEventsRequest can generate the correct url when
// attachments are requested.
TEST_F(CalendarApiRequestsTest, GetEventListRequestWithAttachments) {
ApiErrorCode error = OTHER_ERROR;
std::unique_ptr<EventList> events;
base::Time start;
base::Time end;
EXPECT_TRUE(base::Time::FromString("13 Jun 2021 10:00 GMT", &start));
EXPECT_TRUE(base::Time::FromString("16 Jun 2021 10:00 GMT", &end));
{
base::RunLoop run_loop;
auto request = std::make_unique<CalendarApiEventsRequest>(
request_sender_.get(), *url_generator_,
test_util::CreateQuitCallback(
&run_loop, test_util::CreateCopyResultCallback(&error, &events)),
start, end, /*include_attachments=*/true);
request_sender_->StartRequestWithAuthRetry(std::move(request));
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
EXPECT_EQ(
"/calendar/v3/calendars/primary/events"
"?timeMin=2021-06-13T10%3A00%3A00.000Z"
"&timeMax=2021-06-16T10%3A00%3A00.000Z"
"&singleEvents=true"
"&maxAttendees=1"
"&maxResults=2500"
"&fields=timeZone%2Cetag%2Ckind%2Citems(id%2Ckind"
"%2Csummary%2CcolorId%2Cstatus"
"%2Cstart(date)%2Cend(date)"
"%2Cstart(dateTime)%2Cend(dateTime)"
"%2ChtmlLink%2Cattendees(responseStatus%2Cself)%2CattendeesOmitted"
"%2CconferenceData(conferenceId%2CentryPoints(entryPointType%2Curi))"
"%2Ccreator(self)%2Clocation"
"%2Cattachments(title%2CfileUrl%2CiconLink%2CfileId))",
http_request_.relative_url);
}
} // namespace calendar
} // namespace google_apis