| // 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/accessibility/view_accessibility.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. |
| static constexpr std::u16string_view 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. |
| static constexpr std::u16string_view 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) { |
| static constexpr std::u16string_view kPin(u"6893112"); |
| for (size_t i = 1; i <= kPin.size(); ++i) { |
| LeftClickOn(test_api_pin_keyboard_->digit_button(kPin[i - 1] - u'0')); |
| } |
| static constexpr std::u16string_view kModifiedPin = |
| kPin.substr(0, kPin.size() - 1); |
| EXPECT_CALL(*mock_observer_, OnContentsChanged(kModifiedPin)).Times(1); |
| LeftClickOn(test_api_pin_keyboard_->backspace_button()); |
| EXPECT_EQ(test_api_auth_input_->GetTextfield()->GetText(), kModifiedPin); |
| } |
| |
| // Verify enter press on the textfield submits the pin. |
| TEST_F(PinContainerUnitTest, SubmitTest) { |
| static constexpr std::u16string_view 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) { |
| static constexpr std::u16string_view 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) { |
| static constexpr std::u16string_view 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) { |
| static constexpr std::u16string_view kPin(u"0894329"); |
| test_api_auth_input_->GetTextfield()->SetText(kPin); |
| EXPECT_CALL(*mock_observer_, OnContentsChanged(std::u16string_view())); |
| test_api_->GetView()->ResetState(); |
| } |
| |
| TEST_F(PinContainerUnitTest, AccessibleState) { |
| ui::AXNodeData node_data; |
| container_view_->GetViewAccessibility().GetAccessibleNodeData(&node_data); |
| ASSERT_TRUE(node_data.HasState(ax::mojom::State::kInvisible)); |
| } |
| |
| } // namespace |
| } // namespace ash |