chromium/chrome/browser/apps/app_service/promise_apps/promise_app_almanac_connector_unittest.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/apps/app_service/promise_apps/promise_app_almanac_connector.h"

#include <optional>

#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/bind.h"
#include "base/test/test_future.h"
#include "chrome/browser/apps/app_service/promise_apps/promise_app_wrapper.h"
#include "chrome/browser/apps/app_service/promise_apps/proto/promise_app.pb.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/components/system/fake_statistics_provider.h"
#include "components/services/app_service/public/cpp/package_id.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace apps {

const PackageId kTestPackageId(PackageType::kArc, "test.package.name");

class PromiseAppAlmanacConnectorTest : public testing::Test {
 public:
  PromiseAppAlmanacConnector* connector() { return connector_.get(); }

  void SetUp() override {
    url_loader_factory_ = std::make_unique<network::TestURLLoaderFactory>();
    testing::Test::SetUp();
    TestingProfile::Builder profile_builder;
    profile_builder.SetSharedURLLoaderFactory(
        url_loader_factory_->GetSafeWeakWrapper());
    profile_ = profile_builder.Build();
    test_shared_loader_factory_ = url_loader_factory_->GetSafeWeakWrapper();
    connector_ = std::make_unique<PromiseAppAlmanacConnector>(profile_.get());
    connector_->SetSkipApiKeyCheckForTesting(true);
  }

  network::TestURLLoaderFactory* url_loader_factory() {
    return url_loader_factory_.get();
  }

 private:
  std::unique_ptr<network::TestURLLoaderFactory> url_loader_factory_;
  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
  std::unique_ptr<PromiseAppAlmanacConnector> connector_;
  content::BrowserTaskEnvironment task_environment_;
  ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
  std::unique_ptr<Profile> profile_;
};

TEST_F(PromiseAppAlmanacConnectorTest, GetPromiseAppInfoRequest) {
  std::string method;
  std::optional<std::string> method_override_header;
  std::optional<std::string> content_type;
  std::string body;

  url_loader_factory()->SetInterceptor(
      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
        content_type =
            request.headers.GetHeader(net::HttpRequestHeaders::kContentType);
        method_override_header =
            request.headers.GetHeader("X-HTTP-Method-Override");
        method = request.method;
        body = network::GetUploadData(request);
      }));
  url_loader_factory()->AddResponse(
      PromiseAppAlmanacConnector::GetServerUrl().spec(), /*content=*/"");

  base::test::TestFuture<std::optional<PromiseAppWrapper>> test_callback;
  connector()->GetPromiseAppInfo(kTestPackageId, test_callback.GetCallback());
  EXPECT_TRUE(test_callback.Wait());

  EXPECT_EQ(method, "POST");
  EXPECT_EQ(method_override_header, "GET");
  EXPECT_EQ(content_type, "application/x-protobuf");

  proto::PromiseAppRequest request;
  ASSERT_TRUE(request.ParseFromString(body));
  EXPECT_EQ(request.package_id(), "android:test.package.name");
}

TEST_F(PromiseAppAlmanacConnectorTest, GetPromiseAppInfoSuccessResponse) {
  proto::PromiseAppResponse response;
  response.set_package_id(kTestPackageId.ToString());

  url_loader_factory()->AddResponse(
      PromiseAppAlmanacConnector::GetServerUrl().spec(),
      response.SerializeAsString());

  base::test::TestFuture<std::optional<PromiseAppWrapper>> test_callback;
  connector()->GetPromiseAppInfo(kTestPackageId, test_callback.GetCallback());
  auto promise_app_info = test_callback.Get();

  EXPECT_EQ(promise_app_info->GetPackageId(), kTestPackageId);
}

TEST_F(PromiseAppAlmanacConnectorTest, GetPromiseAppInfoErrorResponse) {
  url_loader_factory()->AddResponse(
      PromiseAppAlmanacConnector::GetServerUrl().spec(), /*content=*/"",
      net::HTTP_INTERNAL_SERVER_ERROR);

  base::test::TestFuture<std::optional<PromiseAppWrapper>> test_callback;
  connector()->GetPromiseAppInfo(kTestPackageId, test_callback.GetCallback());
  auto promise_app_info = test_callback.Get();

  EXPECT_FALSE(promise_app_info.has_value());
}

}  // namespace apps