chromium/ash/glanceables/glanceables_pixeltest.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 <memory>
#include <string>

#include "ash/api/tasks/fake_tasks_client.h"
#include "ash/constants/ash_features.h"
#include "ash/glanceables/classroom/fake_glanceables_classroom_client.h"
#include "ash/glanceables/common/glanceables_view_id.h"
#include "ash/glanceables/glanceables_controller.h"
#include "ash/glanceables/tasks/test/glanceables_tasks_test_util.h"
#include "ash/shelf/shelf.h"
#include "ash/system/unified/date_tray.h"
#include "ash/system/unified/glanceable_tray_bubble.h"
#include "ash/system/unified/glanceable_tray_bubble_view.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/pixel/ash_pixel_differ.h"
#include "ash/test/pixel/ash_pixel_test_init_params.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/time/time_override.h"
#include "ui/views/controls/scroll_view.h"

namespace {
constexpr char kDueDate[] = "2 Aug 2025 10:00 GMT";
}

namespace ash {

class GlanceablesTasksPixelTest : public AshTestBase {
 public:
  GlanceablesTasksPixelTest() {
    time_override_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>(
        []() {
          base::Time date;
          bool result = base::Time::FromString("28 Jul 2023 10:00 GMT", &date);
          DCHECK(result);
          return date;
        },
        /*time_ticks_override=*/nullptr,
        /*thread_ticks_override=*/nullptr);
  }

  // AshTestBase:
  void SetUp() override {
    AshTestBase::SetUp();
    SimulateUserLogin(account_id_);

    base::Time date;
    ASSERT_TRUE(base::Time::FromString(kDueDate, &date));
    fake_glanceables_tasks_client_ =
        glanceables_tasks_test_util::InitializeFakeTasksClient(date);
    Shell::Get()->glanceables_controller()->UpdateClientsRegistration(
        account_id_, GlanceablesController::ClientsRegistration{
                         .tasks_client = fake_glanceables_tasks_client_.get()});
  }

  // AshTestBase:
  void TearDown() override {
    Shell::Get()->glanceables_controller()->UpdateClientsRegistration(
        account_id_, GlanceablesController::ClientsRegistration{});
    AshTestBase::TearDown();
  }

  // AshTestBase:
  std::optional<pixel_test::InitParams> CreatePixelTestInitParams()
      const override {
    return pixel_test::InitParams();
  }

  DateTray* GetDateTray() {
    return GetPrimaryShelf()->GetStatusAreaWidget()->date_tray();
  }

  void ToggleGlanceables() { LeftClickOn(GetDateTray()); }

 protected:
  const AccountId account_id_ =
      AccountId::FromUserEmailGaiaId("[email protected]", "123456");
  std::unique_ptr<api::FakeTasksClient> fake_glanceables_tasks_client_;

 private:
  base::test::ScopedFeatureList features_{
      ash::features::kGlanceablesTimeManagementTasksView};
  std::unique_ptr<base::subtle::ScopedTimeClockOverrides> time_override_;
};

// Pixel test for default / basic glanceables functionality.
TEST_F(GlanceablesTasksPixelTest, Smoke) {
  ASSERT_FALSE(GetDateTray()->is_active());
  ToggleGlanceables();
  ASSERT_TRUE(GetDateTray()->is_active());

  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "glanceables_smoke", /*revision_number=*/0,
      GetDateTray()->glanceables_bubble_for_test()->GetBubbleView()));
}

class GlanceablesTimeManagementPixelTest : public GlanceablesTasksPixelTest {
 public:
  GlanceablesTimeManagementPixelTest() {
    features_.InitWithFeatures(
        /*enabled_features=*/
        {features::kGlanceablesTimeManagementTasksView,
         features::kGlanceablesTimeManagementClassroomStudentView},
        /*disabled_features=*/{});
  }

  // AshTestBase:
  void SetUp() override {
    GlanceablesTasksPixelTest::SetUp();

    base::Time date;
    ASSERT_TRUE(base::Time::FromString(kDueDate, &date));
    // tasks client was initialized in GlanceablesTasksPixelTest.
    classroom_client_ = std::make_unique<FakeGlanceablesClassroomClient>();
    Shell::Get()->glanceables_controller()->UpdateClientsRegistration(
        account_id_, GlanceablesController::ClientsRegistration{
                         .classroom_client = classroom_client_.get(),
                         .tasks_client = fake_glanceables_tasks_client_.get()});

    ASSERT_TRUE(Shell::Get()->glanceables_controller()->GetClassroomClient());
    ASSERT_TRUE(Shell::Get()->glanceables_controller()->GetTasksClient());

    GetDateTray()->ShowGlanceableBubble(/*from_keyboard=*/false);
    view_ = views::AsViewClass<GlanceableTrayBubbleView>(
        GetDateTray()->glanceables_bubble_for_test()->GetBubbleView());
  }

  void TearDown() override {
    GetDateTray()->HideGlanceableBubble();
    view_ = nullptr;
    GlanceablesTasksPixelTest::TearDown();
  }

  GlanceablesTasksView* GetTasksView() const {
    return views::AsViewClass<GlanceablesTasksView>(view_->GetTasksView());
  }

  views::ScrollView* GetTasksScrollView() const {
    return views::AsViewClass<views::ScrollView>(GetTasksView()->GetViewByID(
        base::to_underlying(GlanceablesViewId::kContentsScrollView)));
  }

  GlanceablesClassroomStudentView* GetClassroomView() const {
    return views::AsViewClass<GlanceablesClassroomStudentView>(
        view_->GetClassroomStudentView());
  }

  views::ScrollView* GetClassroomScrollView() const {
    return views::AsViewClass<views::ScrollView>(
        GetClassroomView()->GetViewByID(
            base::to_underlying(GlanceablesViewId::kContentsScrollView)));
  }

 private:
  base::test::ScopedFeatureList features_;
  std::unique_ptr<FakeGlanceablesClassroomClient> classroom_client_;

  raw_ptr<GlanceableTrayBubbleView> view_ = nullptr;
};

// Pixel test for default / basic glanceables functionality.
TEST_F(GlanceablesTimeManagementPixelTest, Smoke) {
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "expanded_tasks_top", /*revision_number=*/1,
      GetDateTray()->glanceables_bubble_for_test()->GetBubbleView()));
  GetTasksScrollView()->ScrollToPosition(
      GetTasksScrollView()->vertical_scroll_bar(), INT_MAX);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "expanded_tasks_bottom", /*revision_number=*/1,
      GetDateTray()->glanceables_bubble_for_test()->GetBubbleView()));

  GetClassroomView()->SetExpandState(true, /*expand_by_overscroll=*/false);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "expanded_classroom_top", /*revision_number=*/1,
      GetDateTray()->glanceables_bubble_for_test()->GetBubbleView()));
  GetClassroomScrollView()->ScrollToPosition(
      GetClassroomScrollView()->vertical_scroll_bar(), INT_MAX);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "expanded_classroom_bottom", /*revision_number=*/1,
      GetDateTray()->glanceables_bubble_for_test()->GetBubbleView()));
}

}  // namespace ash