chromium/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher_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 "gif_tenor_api_fetcher.h"

#include <memory>
#include <string>
#include <vector>

#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom-forward.h"
#include "components/endpoint_fetcher/endpoint_fetcher.h"
#include "content/public/test/browser_task_environment.h"
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"

namespace ash {

namespace {

constexpr char kFakeCategoriesResponse[] = R"json(
  {
    "tags": [
      {
        "image": "url1",
        "name": "#awesome",
        "path": "/v2/path1",
        "searchterm": "awesome"
      },
      {
        "image": "url2",
        "name": "#jk",
        "path": "/v2/path2",
        "searchterm": "jk"
      }
    ]
  }
)json";

constexpr char kFakeGifsResponse[] = R"json(
  {
    "next": "1",
    "results": [
      {
        "id": "0",
        "content_description": "GIF0",
        "media_formats": {
          "gif": {
            "dims": [
              498,
              339
            ],
            "url": "https://tenor.com/view/media.tenor.com/full_url0",
            "preview": ""
          },
          "tinygif": {
            "dims": [
              220,
              150
            ],
            "url": "https://tenor.com/view/media.tenor.com/preview_url0",
            "preview": ""
          },
          "tinygifpreview": {
            "dims": [
              220,
              150
            ],
            "url": "https://tenor.com/view/media.tenor.com/preview_image_url0",
            "preview": ""
          }
        }
      },
      {
        "id": "1",
        "content_description": "GIF1",
        "media_formats": {
          "gif": {
            "dims": [
              498,
              498
            ],
            "url": "https://tenor.com/view/media.tenor.com/full_url1",
            "preview": ""
          },
          "tinygif": {
            "dims": [
              220,
              220
            ],
            "url": "https://tenor.com/view/media.tenor.com/preview_url1",
            "preview": ""
          },
          "tinygifpreview": {
            "dims": [
              220,
              220
            ],
            "url": "https://tenor.com/view/media.tenor.com/preview_image_url1",
            "preview": ""
          }
        }
      }
    ]
  }
)json";

std::vector<emoji_picker::mojom::GifResponsePtr> GetFakeGifs() {
  std::vector<emoji_picker::mojom::GifResponsePtr> gifs;
  gifs.push_back(emoji_picker::mojom::GifResponse::New(
      "0", "GIF0",
      emoji_picker::mojom::GifUrls::New(
          GURL("https://tenor.com/view/media.tenor.com/full_url0"),
          GURL("https://tenor.com/view/media.tenor.com/preview_url0"),
          GURL("https://tenor.com/view/media.tenor.com/preview_image_url0")),
      gfx::Size(220, 150), gfx::Size(498, 339)));
  gifs.push_back(emoji_picker::mojom::GifResponse::New(
      "1", "GIF1",
      emoji_picker::mojom::GifUrls::New(
          GURL("https://tenor.com/view/media.tenor.com/full_url1"),
          GURL("https://tenor.com/view/media.tenor.com/preview_url1"),
          GURL("https://tenor.com/view/media.tenor.com/preview_image_url1")),
      gfx::Size(220, 220), gfx::Size(498, 498)));
  return gifs;
}
}  // namespace

class FakeEndpointFetcher : public EndpointFetcher {
 public:
  explicit FakeEndpointFetcher(EndpointResponse response)
      : EndpointFetcher(net::DefineNetworkTrafficAnnotation(
            "chromeos_emoji_picker_mock_fetcher",
            R"()")),
        response_(response) {}

  void PerformRequest(EndpointFetcherCallback endpoint_fetcher_callback,
                      const char* key) override {
    std::move(endpoint_fetcher_callback)
        .Run(std::make_unique<EndpointResponse>(response_));
  }

 private:
  EndpointResponse response_;
};

class GifTenorApiFetcherTest : public testing::Test {
 public:
  GifTenorApiFetcherTest()
      : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP,
                          base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}

  std::unique_ptr<EndpointFetcher> CreateEndpointFetcher(
      const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      const GURL& url,
      const net::NetworkTrafficAnnotationTag& annotation_tag) {
    return std::make_unique<FakeEndpointFetcher>(response_);
  }

 protected:
  content::BrowserTaskEnvironment task_environment_;
  EndpointResponse response_;
  data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
  GifTenorApiFetcher gif_tenor_api_fetcher_ = GifTenorApiFetcher(
      base::BindRepeating(&GifTenorApiFetcherTest::CreateEndpointFetcher,
                          base::Unretained(this)));
};

TEST_F(GifTenorApiFetcherTest, FetchCategories) {
  task_environment_.RunUntilIdle();
  base::test::TestFuture<emoji_picker::mojom::Status,
                         const std::vector<std::string>&>
      create_future_http_error;
  gif_tenor_api_fetcher_.FetchCategories(create_future_http_error.GetCallback(),
                                         url_loader_factory_);
  ASSERT_EQ(create_future_http_error.Get<0>(),
            emoji_picker::mojom::Status::kHttpError);
  ASSERT_EQ(create_future_http_error.Get<1>(), std::vector<std::string>{});

  response_.error_type = std::make_optional(FetchErrorType::kNetError);
  base::test::TestFuture<emoji_picker::mojom::Status,
                         const std::vector<std::string>&>
      create_future_net_error;
  gif_tenor_api_fetcher_.FetchCategories(create_future_net_error.GetCallback(),
                                         url_loader_factory_);
  ASSERT_EQ(create_future_net_error.Get<0>(),
            emoji_picker::mojom::Status::kNetError);
  ASSERT_EQ(create_future_net_error.Get<1>(), std::vector<std::string>{});

  base::test::TestFuture<emoji_picker::mojom::Status,
                         const std::vector<std::string>&>
      create_future_http_ok;
  response_.response = kFakeCategoriesResponse;
  response_.http_status_code = net::HTTP_OK;
  gif_tenor_api_fetcher_.FetchCategories(create_future_http_ok.GetCallback(),
                                         url_loader_factory_);
  std::vector<std::string> expected{"#awesome", "#jk"};
  ASSERT_EQ(create_future_http_ok.Get<0>(),
            emoji_picker::mojom::Status::kHttpOk);
  ASSERT_EQ(create_future_http_ok.Get<1>(), expected);
}

TEST_F(GifTenorApiFetcherTest, FetchFeaturedGifs) {
  task_environment_.RunUntilIdle();
  base::test::TestFuture<emoji_picker::mojom::Status,
                         emoji_picker::mojom::TenorGifResponsePtr>
      create_future_http_error;
  gif_tenor_api_fetcher_.FetchFeaturedGifs(
      create_future_http_error.GetCallback(), url_loader_factory_, "");
  ASSERT_EQ(create_future_http_error.Get<0>(),
            emoji_picker::mojom::Status::kHttpError);
  ASSERT_EQ(create_future_http_error.Get<1>(),
            emoji_picker::mojom::TenorGifResponse::New(
                "", std::vector<emoji_picker::mojom::GifResponsePtr>{}));

  response_.error_type = std::make_optional(FetchErrorType::kNetError);
  base::test::TestFuture<emoji_picker::mojom::Status,
                         emoji_picker::mojom::TenorGifResponsePtr>
      create_future_net_error;
  gif_tenor_api_fetcher_.FetchFeaturedGifs(
      create_future_net_error.GetCallback(), url_loader_factory_, "");
  ASSERT_EQ(create_future_net_error.Get<0>(),
            emoji_picker::mojom::Status::kNetError);
  ASSERT_EQ(create_future_net_error.Get<1>(),
            emoji_picker::mojom::TenorGifResponse::New(
                "", std::vector<emoji_picker::mojom::GifResponsePtr>{}));

  response_.response = kFakeGifsResponse;
  response_.http_status_code = net::HTTP_OK;
  base::test::TestFuture<emoji_picker::mojom::Status,
                         emoji_picker::mojom::TenorGifResponsePtr>
      create_future_http_ok;
  gif_tenor_api_fetcher_.FetchFeaturedGifs(create_future_http_ok.GetCallback(),
                                           url_loader_factory_, "");
  ASSERT_EQ(create_future_http_ok.Get<0>(),
            emoji_picker::mojom::Status::kHttpOk);
  ASSERT_EQ(create_future_http_ok.Get<1>(),
            emoji_picker::mojom::TenorGifResponse::New("1", GetFakeGifs()));
}

TEST_F(GifTenorApiFetcherTest, FetchGifSearch) {
  task_environment_.RunUntilIdle();
  base::test::TestFuture<emoji_picker::mojom::Status,
                         emoji_picker::mojom::TenorGifResponsePtr>
      create_future_http_error;
  gif_tenor_api_fetcher_.FetchGifSearch(create_future_http_error.GetCallback(),
                                        url_loader_factory_, "", "");
  ASSERT_EQ(create_future_http_error.Get<0>(),
            emoji_picker::mojom::Status::kHttpError);
  ASSERT_EQ(create_future_http_error.Get<1>(),
            emoji_picker::mojom::TenorGifResponse::New(
                "", std::vector<emoji_picker::mojom::GifResponsePtr>{}));

  response_.error_type = std::make_optional(FetchErrorType::kNetError);
  base::test::TestFuture<emoji_picker::mojom::Status,
                         emoji_picker::mojom::TenorGifResponsePtr>
      create_future_net_error;
  gif_tenor_api_fetcher_.FetchFeaturedGifs(
      create_future_net_error.GetCallback(), url_loader_factory_, "");
  ASSERT_EQ(create_future_net_error.Get<0>(),
            emoji_picker::mojom::Status::kNetError);
  ASSERT_EQ(create_future_net_error.Get<1>(),
            emoji_picker::mojom::TenorGifResponse::New(
                "", std::vector<emoji_picker::mojom::GifResponsePtr>{}));

  response_.response = kFakeGifsResponse;
  response_.http_status_code = net::HTTP_OK;
  base::test::TestFuture<emoji_picker::mojom::Status,
                         emoji_picker::mojom::TenorGifResponsePtr>
      create_future_http_ok;
  gif_tenor_api_fetcher_.FetchFeaturedGifs(create_future_http_ok.GetCallback(),
                                           url_loader_factory_, "");
  ASSERT_EQ(create_future_http_ok.Get<0>(),
            emoji_picker::mojom::Status::kHttpOk);
  ASSERT_EQ(create_future_http_ok.Get<1>(),
            emoji_picker::mojom::TenorGifResponse::New("1", GetFakeGifs()));
}

TEST_F(GifTenorApiFetcherTest, FetchGifsByIds) {
  task_environment_.RunUntilIdle();
  base::test::TestFuture<emoji_picker::mojom::Status,
                         std::vector<emoji_picker::mojom::GifResponsePtr>>
      create_future_http_error;
  gif_tenor_api_fetcher_.FetchGifsByIds(create_future_http_error.GetCallback(),
                                        url_loader_factory_,
                                        std::vector<std::string>());
  ASSERT_EQ(create_future_http_error.Get<0>(),
            emoji_picker::mojom::Status::kHttpError);
  ASSERT_EQ(create_future_http_error.Get<1>(),
            std::vector<emoji_picker::mojom::GifResponsePtr>{});

  response_.error_type = std::make_optional(FetchErrorType::kNetError);
  base::test::TestFuture<emoji_picker::mojom::Status,
                         std::vector<emoji_picker::mojom::GifResponsePtr>>
      create_future_net_error;
  gif_tenor_api_fetcher_.FetchGifsByIds(create_future_net_error.GetCallback(),
                                        url_loader_factory_,
                                        std::vector<std::string>());
  ASSERT_EQ(create_future_net_error.Get<0>(),
            emoji_picker::mojom::Status::kNetError);
  ASSERT_EQ(create_future_net_error.Get<1>(),
            std::vector<emoji_picker::mojom::GifResponsePtr>{});

  response_.response = kFakeGifsResponse;
  response_.http_status_code = net::HTTP_OK;
  base::test::TestFuture<emoji_picker::mojom::Status,
                         std::vector<emoji_picker::mojom::GifResponsePtr>>
      create_future_http_ok;
  gif_tenor_api_fetcher_.FetchGifsByIds(create_future_http_ok.GetCallback(),
                                        url_loader_factory_,
                                        std::vector<std::string>());
  ASSERT_EQ(create_future_http_ok.Get<0>(),
            emoji_picker::mojom::Status::kHttpOk);
  ASSERT_EQ(create_future_http_ok.Get<1>(), GetFakeGifs());
}

}  // namespace ash