chromium/ash/system/phonehub/camera_roll_view_unittest.cc

// 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/phonehub/camera_roll_view.h"

#include "ash/system/phonehub/camera_roll_thumbnail.h"
#include "ash/system/phonehub/phone_hub_metrics.h"
#include "ash/test/ash_test_base.h"
#include "chromeos/ash/components/phonehub/camera_roll_item.h"
#include "chromeos/ash/components/phonehub/fake_camera_roll_manager.h"
#include "chromeos/ash/components/phonehub/fake_user_action_recorder.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/compositor/property_change_reason.h"
#include "ui/gfx/image/image.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/test/views_test_utils.h"
#include "ui/views/view.h"

namespace ash {

class CameraRollViewForTest : public CameraRollView {
 public:
  CameraRollViewForTest(phonehub::CameraRollManager* camera_roll_manager,
                        phonehub::UserActionRecorder* user_action_recorder)
      : CameraRollView(camera_roll_manager, user_action_recorder) {}
  ~CameraRollViewForTest() override = default;
};

class CameraRollViewTest : public AshTestBase {
 public:
  CameraRollViewTest() = default;
  ~CameraRollViewTest() override = default;

  // AshTestBase:
  void TearDown() override {
    camera_roll_view_.reset();
    fake_camera_roll_manager_.reset();
    AshTestBase::TearDown();
  }

 protected:
  const CameraRollView* camera_roll_view() const {
    return camera_roll_view_.get();
  }

  phonehub::FakeCameraRollManager* fake_camera_roll_manager() {
    return fake_camera_roll_manager_.get();
  }

  void PresetCameraRollOptInState(bool can_be_enabled) {
    fake_camera_roll_manager_ =
        std::make_unique<phonehub::FakeCameraRollManager>();
    fake_camera_roll_manager_->SetIsCameraRollAvailableToBeEnabled(
        can_be_enabled);
    fake_user_action_recorder_ =
        std::make_unique<phonehub::FakeUserActionRecorder>();
    camera_roll_view_ = std::make_unique<CameraRollViewForTest>(
        fake_camera_roll_manager_.get(), fake_user_action_recorder_.get());
  }

  const std::vector<phonehub::CameraRollItem> CreateFakeItems(int num) {
    std::vector<phonehub::CameraRollItem> items;
    for (int i = num; i > 0; --i) {
      phonehub::proto::CameraRollItemMetadata metadata;
      metadata.set_key(base::NumberToString(i));
      metadata.set_mime_type("image/jpeg");
      metadata.set_last_modified_millis(1577865600 + i);
      metadata.set_file_size_bytes(123456);
      metadata.set_file_name("fake_file_" + base::NumberToString(i) + ".jpg");

      SkBitmap bitmap;
      bitmap.allocN32Pixels(96, 96);
      gfx::Image thumbnail = gfx::Image::CreateFrom1xBitmap(bitmap);

      items.emplace_back(metadata, thumbnail);
    }
    return items;
  }

  const std::vector<phonehub::CameraRollItem> CreateSingleItemWithType(
      bool is_video) {
    phonehub::proto::CameraRollItemMetadata metadata;
    metadata.set_key("key");
    metadata.set_last_modified_millis(1577865600);
    metadata.set_file_size_bytes(123456);

    if (is_video) {
      metadata.set_mime_type("video/mp4");
      metadata.set_file_name("fake_video.mp4");
    } else {
      metadata.set_mime_type("image/png");
      metadata.set_file_name("fake_image.png");
    }

    SkBitmap bitmap;
    bitmap.allocN32Pixels(1, 1);
    gfx::Image thumbnail = gfx::Image::CreateFrom1xBitmap(bitmap);

    return std::vector<phonehub::CameraRollItem>{
        phonehub::CameraRollItem(metadata, thumbnail)};
  }

  CameraRollView::CameraRollItemsView* GetItemsView() const {
    return static_cast<CameraRollView::CameraRollItemsView*>(
        camera_roll_view()->children().at(1));
  }

  CameraRollThumbnail* GetThumbnailView(int index) const {
    return static_cast<CameraRollThumbnail*>(
        GetItemsView()->children().at(index));
  }

 private:
  std::unique_ptr<CameraRollView> camera_roll_view_;
  std::unique_ptr<phonehub::FakeUserActionRecorder> fake_user_action_recorder_;
  std::unique_ptr<phonehub::FakeCameraRollManager> fake_camera_roll_manager_;
};

TEST_F(CameraRollViewTest, OptInAlready) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);

  fake_camera_roll_manager()->ClearCurrentItems();
  EXPECT_FALSE(camera_roll_view()->GetVisible());

  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(1));
  EXPECT_TRUE(camera_roll_view()->GetVisible());
  EXPECT_TRUE(camera_roll_view()->items_view_->GetVisible());
}

TEST_F(CameraRollViewTest, OptInAndDismissed) {
  PresetCameraRollOptInState(/*can_be_enabled=*/true);

  fake_camera_roll_manager()->ClearCurrentItems();
  EXPECT_FALSE(camera_roll_view()->GetVisible());
  // Setting disabled, shouldn't display anything even if there are camera roll
  // items
  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(1));
  EXPECT_FALSE(camera_roll_view()->GetVisible());
}

TEST_F(CameraRollViewTest, ViewVisibility) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  // The camera roll view is not visible if there are no items available and
  // visible when there are one or more items available.
  fake_camera_roll_manager()->ClearCurrentItems();
  EXPECT_FALSE(camera_roll_view()->GetVisible());

  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(1));
  EXPECT_TRUE(camera_roll_view()->GetVisible());

  fake_camera_roll_manager()->ClearCurrentItems();
  EXPECT_FALSE(camera_roll_view()->GetVisible());
}

TEST_F(CameraRollViewTest, SingleItem) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  // Set 1 camera roll item.
  size_t expected_size = 1;
  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(expected_size));
  EXPECT_EQ(GetItemsView()->children().size(), expected_size);
}

TEST_F(CameraRollViewTest, MultipleItems) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  // Set 4 camera roll items.
  size_t expected_size = 4;
  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(expected_size));
  EXPECT_EQ(GetItemsView()->children().size(), expected_size);
}

TEST_F(CameraRollViewTest, ViewLayout) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  // Test the layout size and positions of the items. If the layout is being
  // intentionally changed this test will need to be updated.
  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(4));
  views::test::RunScheduledLayout(GetItemsView());
  EXPECT_EQ(GetItemsView()->CalculatePreferredSize({}), gfx::Size(328, 82));
  EXPECT_EQ(GetThumbnailView(0)->bounds(), gfx::Rect(4, 4, 74, 74));
  EXPECT_EQ(GetThumbnailView(1)->bounds(), gfx::Rect(86, 4, 74, 74));
  EXPECT_EQ(GetThumbnailView(2)->bounds(), gfx::Rect(168, 4, 74, 74));
  EXPECT_EQ(GetThumbnailView(3)->bounds(), gfx::Rect(250, 4, 74, 74));
}

TEST_F(CameraRollViewTest, AccessibleNameAndTooltip) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  fake_camera_roll_manager()->SetCurrentItems(CreateFakeItems(4));

  EXPECT_EQ(u"Recent photo 1 of 4.",
            GetThumbnailView(0)->GetViewAccessibility().GetCachedName());
  EXPECT_EQ(u"Recent photo 1 of 4.", GetThumbnailView(0)->GetTooltipText());
  EXPECT_EQ(u"Recent photo 2 of 4.",
            GetThumbnailView(1)->GetViewAccessibility().GetCachedName());
  EXPECT_EQ(u"Recent photo 2 of 4.", GetThumbnailView(1)->GetTooltipText());
  EXPECT_EQ(u"Recent photo 3 of 4.",
            GetThumbnailView(2)->GetViewAccessibility().GetCachedName());
  EXPECT_EQ(u"Recent photo 3 of 4.", GetThumbnailView(2)->GetTooltipText());
  EXPECT_EQ(u"Recent photo 4 of 4.",
            GetThumbnailView(3)->GetViewAccessibility().GetCachedName());
  EXPECT_EQ(u"Recent photo 4 of 4.", GetThumbnailView(3)->GetTooltipText());
}

TEST_F(CameraRollViewTest, ImageThumbnail) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  fake_camera_roll_manager()->SetCurrentItems(
      CreateSingleItemWithType(/*is_video=*/false));

  EXPECT_EQ(GetThumbnailView(0)->GetMediaType(),
            phone_hub_metrics::CameraRollMediaType::kPhoto);
}

TEST_F(CameraRollViewTest, VideoThumbnail) {
  PresetCameraRollOptInState(/*can_be_enabled=*/false);
  fake_camera_roll_manager()->SetCurrentItems(
      CreateSingleItemWithType(/*is_video=*/true));

  EXPECT_EQ(GetThumbnailView(0)->GetMediaType(),
            phone_hub_metrics::CameraRollMediaType::kVideo);
}

}  // namespace ash