chromium/ash/auth/views/auth_container_view_pixeltest.cc

// Copyright 2024 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 <optional>

#include "ash/auth/views/auth_container_view.h"
#include "ash/auth/views/auth_input_row_view.h"
#include "ash/auth/views/fingerprint_view.h"
#include "ash/auth/views/pin_keyboard_view.h"
#include "ash/auth/views/test_support/mock_auth_container_view_observer.h"
#include "ash/public/cpp/login_types.h"
#include "ash/style/dark_light_mode_controller_impl.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/ash_test_util.h"
#include "ash/test/pixel/ash_pixel_differ.h"
#include "ash/test/pixel/ash_pixel_test_init_params.h"
#include "base/containers/enum_set.h"
#include "base/files/file_path.h"
#include "ui/views/test/views_test_utils.h"
#include "ui/views/view.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"

namespace ash {

namespace {

class AuthContainerPixelTest : public AshTestBase {
 public:
  AuthContainerPixelTest() = default;
  AuthContainerPixelTest(const AuthContainerPixelTest&) = delete;
  AuthContainerPixelTest& operator=(const AuthContainerPixelTest&) = delete;
  ~AuthContainerPixelTest() override = default;

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

 protected:
  void SetUp() override {
    AshTestBase::SetUp();

    widget_ = CreateFramelessTestWidget();
    widget_->SetFullscreen(true);
    widget_->Show();

    container_view_ =
        widget_->SetContentsView(std::make_unique<AuthContainerView>(
            AuthFactorSet{AuthInputType::kPassword, AuthInputType::kPin}));
    test_api_ = std::make_unique<AuthContainerView::TestApi>(container_view_);
    test_api_pin_container_ = std::make_unique<PinContainerView::TestApi>(
        test_api_->GetPinContainerView());
    test_api_pin_keyboard_ = std::make_unique<PinKeyboardView::TestApi>(
        test_api_pin_container_->GetPinKeyboardView());
    test_api_pin_input_ = std::make_unique<AuthInputRowView::TestApi>(
        test_api_pin_container_->GetAuthInputRowView());

    test_api_password_ = std::make_unique<AuthInputRowView::TestApi>(
        test_api_->GetPasswordView());
    test_api_pin_status_ =
        std::make_unique<PinStatusView::TestApi>(test_api_->GetPinStatusView());

    // At start the the password is visible and the pin is hidden.
    CHECK(test_api_password_->GetView()->GetVisible());
    CHECK(!test_api_pin_container_->GetView()->GetVisible());
    CHECK(!test_api_pin_status_->GetView()->GetVisible());
    CHECK(test_api_->GetSwitchButton()->GetVisible());

    // Test the views in day mode.
    DarkLightModeControllerImpl::Get()->SetDarkModeEnabledForTest(false);
  }

  void TearDown() override {
    test_api_pin_input_.reset();
    test_api_pin_keyboard_.reset();
    test_api_pin_container_.reset();
    test_api_password_.reset();
    test_api_pin_status_.reset();
    test_api_.reset();
    container_view_ = nullptr;
    widget_.reset();
    AshTestBase::TearDown();
  }

  std::unique_ptr<views::Widget> widget_;
  std::unique_ptr<AuthInputRowView::TestApi> test_api_pin_input_;
  std::unique_ptr<PinKeyboardView::TestApi> test_api_pin_keyboard_;
  std::unique_ptr<PinContainerView::TestApi> test_api_pin_container_;
  std::unique_ptr<AuthInputRowView::TestApi> test_api_password_;
  std::unique_ptr<PinStatusView::TestApi> test_api_pin_status_;
  std::unique_ptr<AuthContainerView::TestApi> test_api_;
  raw_ptr<AuthContainerView> container_view_ = nullptr;
};

// Verify the container view with the switch button.
TEST_F(AuthContainerPixelTest, SwitchTest) {
  //  Verify the UI.
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordWithSwitch", /*revision_number=*/0, container_view_));
  // Switch to the pin UI.
  LeftClickOn(test_api_->GetSwitchButton());

  //  Verify the UI.
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PinWithSwitch", /*revision_number=*/0, container_view_));
}

// Verify the PIN only UI.
TEST_F(AuthContainerPixelTest, PinOnlyTest) {
  // Turn off the password factor availability.
  test_api_->GetView()->SetHasPassword(false);

  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PinOnly", /*revision_number=*/0, container_view_));
}

// Verify the password only UI.
TEST_F(AuthContainerPixelTest, PasswordOnlyTest) {
  // Turn off the PIN factor availability.
  test_api_->GetView()->SetHasPin(false);

  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordOnly", /*revision_number=*/0, container_view_));
}

// Verify the password only UI with a PIN status.
TEST_F(AuthContainerPixelTest, PinStatusTest) {
  // For better visibility
  container_view_->SetBackground(
      views::CreateThemedSolidBackground(cros_tokens::kCrosSysBaseElevated));

  // Turn off the PIN factor availability.
  test_api_->GetView()->SetHasPin(false);

  const std::u16string status_message = u"Too many failed attempts.";
  test_api_->GetView()->SetPinStatus(status_message);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "SetPinStatus", /*revision_number=*/0, container_view_));

  test_api_->GetView()->SetPinStatus(u"");
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordOnly", /*revision_number=*/0, container_view_));
}

// Verify the fingerprint view.
TEST_F(AuthContainerPixelTest, PasswordWithFingerprintTest) {
  // For better visibility
  container_view_->SetBackground(
      views::CreateThemedSolidBackground(cros_tokens::kCrosSysBaseElevated));

  test_api_->GetView()->SetHasPin(false);
  // Turn on the fingerprint factor availability.
  container_view_->SetFingerprintState(FingerprintState::AVAILABLE_DEFAULT);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordWithFingerprint", /*revision_number=*/0, container_view_));

  // Turn off the fingerprint factor availability.
  container_view_->SetFingerprintState(FingerprintState::UNAVAILABLE);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordWithHiddenFingerprint", /*revision_number=*/0, container_view_));
}

// Verify the fingerprint view.
TEST_F(AuthContainerPixelTest, PasswordAndPinWithFingerprintTest) {
  // For better visibility
  container_view_->SetBackground(
      views::CreateThemedSolidBackground(cros_tokens::kCrosSysBaseElevated));

  test_api_->GetView()->SetHasPin(true);
  // Turn on the fingerprint factor availability.
  container_view_->SetFingerprintState(FingerprintState::AVAILABLE_DEFAULT);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordAndPinWithFingerprint", /*revision_number=*/0, container_view_));

  // Turn on the fingerprint factor availability.
  container_view_->SetFingerprintState(FingerprintState::UNAVAILABLE);
  EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
      "PasswordAndPinWithHiddenFingerprint", /*revision_number=*/0,
      container_view_));
}

}  // namespace
}  // namespace ash