chromium/ash/auth/views/pin_container_view_unittest.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 "ash/auth/views/pin_container_view.h"

#include <memory>
#include <optional>

#include "ash/auth/views/auth_input_row_view.h"
#include "ash/auth/views/pin_keyboard_view.h"
#include "ash/auth/views/test_support/mock_auth_input_row_view_observer.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/ash_test_util.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

namespace ash {

namespace {

typedef MockAuthInputRowViewObserver MockPinContainerViewObserver;

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

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

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

    container_view_ =
        widget_->SetContentsView(std::make_unique<PinContainerView>());
    test_api_ = std::make_unique<PinContainerView::TestApi>(container_view_);
    test_api_pin_keyboard_ = std::make_unique<PinKeyboardView::TestApi>(
        test_api_->GetPinKeyboardView());
    test_api_auth_input_ = std::make_unique<AuthInputRowView::TestApi>(
        test_api_->GetAuthInputRowView());

    mock_observer_ = std::make_unique<MockPinContainerViewObserver>();
    container_view_->AddObserver(mock_observer_.get());
  }

  void TearDown() override {
    test_api_pin_keyboard_.reset();
    test_api_auth_input_.reset();
    test_api_.reset();
    container_view_->RemoveObserver(mock_observer_.get());
    mock_observer_.reset();
    container_view_ = nullptr;
    widget_.reset();
    AshTestBase::TearDown();
  }

  std::unique_ptr<views::Widget> widget_;
  std::unique_ptr<MockPinContainerViewObserver> mock_observer_;
  std::unique_ptr<PinKeyboardView::TestApi> test_api_pin_keyboard_;
  std::unique_ptr<AuthInputRowView::TestApi> test_api_auth_input_;
  std::unique_ptr<PinContainerView::TestApi> test_api_;
  raw_ptr<PinContainerView> container_view_ = nullptr;
};

// Verify pin keyboard connected with auth input row.
TEST_F(PinContainerUnitTest, TypePin) {
  // Press 1,2,3,4,5,6 buttons on the pin pad.
  const std::u16string kPin(u"123456");
  for (size_t i = 1; i <= kPin.size(); ++i) {
    EXPECT_CALL(*mock_observer_, OnContentsChanged(kPin.substr(0, i))).Times(1);
    LeftClickOn(test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0'));
  }
  EXPECT_EQ(test_api_auth_input_->GetTextfield()->GetText(), kPin);
}

// Verify type is not operating with disabled input.
TEST_F(PinContainerUnitTest, DisabledTypePin) {
  container_view_->SetInputEnabled(false);
  // Press 1,2,3,4,5,6 buttons on the pin pad.
  const std::u16string kPin(u"123456");
  for (size_t i = 1; i <= kPin.size(); ++i) {
    LeftClickOn(test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0'));
  }
  EXPECT_EQ(test_api_auth_input_->GetTextfield()->GetText(), std::u16string());
}

// Verify pin keyboard connected with auth input row.
TEST_F(PinContainerUnitTest, BackspaceTest) {
  const std::u16string kPin(u"6893112");
  for (size_t i = 1; i <= kPin.size(); ++i) {
    LeftClickOn(test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0'));
  }
  const std::u16string modified_pin = kPin.substr(0, kPin.size() - 1);
  EXPECT_CALL(*mock_observer_, OnContentsChanged(modified_pin)).Times(1);
  LeftClickOn(test_api_pin_keyboard_->backspace_button());
  EXPECT_EQ(test_api_auth_input_->GetTextfield()->GetText(), modified_pin);
}

// Verify enter press on the textfield submits the pin.
TEST_F(PinContainerUnitTest, SubmitTest) {
  const std::u16string kPin(u"60012345");
  // Set textfield to be focused.
  container_view_->GetFocusManager()->SetFocusedView(
      test_api_auth_input_->GetTextfield());
  for (size_t i = 1; i <= kPin.size(); ++i) {
    LeftClickOn(test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0'));
  }
  EXPECT_CALL(*mock_observer_, OnSubmit(kPin)).Times(1);
  PressAndReleaseKey(ui::VKEY_RETURN);
}

// Verify enter press is not operating with disabled input.
TEST_F(PinContainerUnitTest, SubmitDisabledTest) {
  const std::u16string kPin(u"60012345");
  // Set textfield to be focused.
  container_view_->GetFocusManager()->SetFocusedView(
      test_api_auth_input_->GetTextfield());
  for (size_t i = 1; i <= kPin.size(); ++i) {
    LeftClickOn(test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0'));
  }
  container_view_->SetInputEnabled(false);
  EXPECT_CALL(*mock_observer_, OnSubmit(kPin)).Times(0);
  PressAndReleaseKey(ui::VKEY_RETURN);
}

// Verify enter press on the digit presses the key.
TEST_F(PinContainerUnitTest, EnterOnPinkeyboardTest) {
  const std::u16string kPin(u"0894329");
  for (size_t i = 1; i <= kPin.size(); ++i) {
    // Set digit key to be focused and press enter on the button.
    container_view_->GetFocusManager()->SetFocusedView(
        test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0'));
    EXPECT_CALL(*mock_observer_, OnContentsChanged(kPin.substr(0, i))).Times(1);
    PressAndReleaseKey(ui::VKEY_RETURN);
  }
}

// Verify the ResetState functionality.
TEST_F(PinContainerUnitTest, ResetStateTest) {
  const std::u16string kPin(u"0894329");
  test_api_auth_input_->GetTextfield()->SetText(kPin);
  EXPECT_CALL(*mock_observer_, OnContentsChanged(std::u16string()));
  test_api_->GetView()->ResetState();
}

}  // namespace
}  // namespace ash