| // 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/auth_textfield.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include "ash/auth/views/test_support/mock_auth_textfield_observer.h" |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/check.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/strings/strcat.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/aura/window.h" |
| #include "ui/events/event.h" |
| #include "ui/events/test/event_generator.h" |
| #include "ui/events/types/event_type.h" |
| #include "ui/gfx/geometry/point.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/views/widget/widget.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| constexpr std::u16string_view kPassword = u"password"; |
| constexpr std::u16string_view kPin = u"123456"; |
| |
| } // namespace |
| |
| class PasswordTextfieldUnitTest : public AshTestBase { |
| public: |
| PasswordTextfieldUnitTest() = default; |
| PasswordTextfieldUnitTest(const PasswordTextfieldUnitTest&) = delete; |
| PasswordTextfieldUnitTest& operator=(const PasswordTextfieldUnitTest&) = |
| delete; |
| ~PasswordTextfieldUnitTest() override = default; |
| |
| void SetTextfieldToFocus() { |
| auth_textfield_->GetFocusManager()->SetFocusedView(auth_textfield_); |
| } |
| |
| protected: |
| // AshTestBase: |
| void SetUp() override { |
| AshTestBase::SetUp(); |
| |
| widget_ = CreateFramelessTestWidget(); |
| widget_->SetFullscreen(true); |
| widget_->Show(); |
| |
| auth_textfield_ = widget_->SetContentsView( |
| std::make_unique<AuthTextfield>(AuthTextfield::AuthType::kPassword)); |
| mock_observer_ = std::make_unique<MockAuthTextfieldObserver>(); |
| auth_textfield_->AddObserver(mock_observer_.get()); |
| } |
| |
| void TearDown() override { |
| AshTestBase::TearDown(); |
| auth_textfield_->RemoveObserver(mock_observer_.get()); |
| mock_observer_.reset(); |
| auth_textfield_ = nullptr; |
| widget_.reset(); |
| } |
| |
| std::unique_ptr<views::Widget> widget_; |
| std::unique_ptr<MockAuthTextfieldObserver> mock_observer_; |
| raw_ptr<AuthTextfield> auth_textfield_; |
| }; |
| |
| // Testing textfield OnBlur Observer. |
| TEST_F(PasswordTextfieldUnitTest, OnBlurObserverTest) { |
| EXPECT_CALL(*mock_observer_, OnTextfieldBlur()).Times(1); |
| auth_textfield_->OnBlur(); |
| } |
| |
| // Testing textfield OnFocus Observer. |
| TEST_F(PasswordTextfieldUnitTest, OnFocusObserverTest) { |
| EXPECT_CALL(*mock_observer_, OnTextfieldFocus()).Times(1); |
| SetTextfieldToFocus(); |
| } |
| |
| // Testing textfield OnContentsChanged Observer. |
| TEST_F(PasswordTextfieldUnitTest, OnContentsChangedTest) { |
| auth_textfield_->SetText(kPassword); |
| SetTextfieldToFocus(); |
| const std::u16string modified_string = base::StrCat({kPassword, u"s"}); |
| EXPECT_CALL(*mock_observer_, |
| OnContentsChanged(std::u16string_view(modified_string))) |
| .Times(1); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_S); |
| } |
| |
| // Testing textfield OnTextVisibleChanged Observer. |
| TEST_F(PasswordTextfieldUnitTest, OnTextVisibleChangedTest) { |
| auth_textfield_->SetText(kPassword); |
| SetTextfieldToFocus(); |
| // by default the password should be hidden. |
| CHECK(!auth_textfield_->IsTextVisible()); |
| EXPECT_CALL(*mock_observer_, OnTextVisibleChanged(true)).Times(1); |
| auth_textfield_->SetTextVisible(true); |
| CHECK(auth_textfield_->IsTextVisible()); |
| } |
| |
| // Testing password textfield OnSubmit Observer. |
| TEST_F(PasswordTextfieldUnitTest, OnSubmitTest) { |
| auth_textfield_->SetText(kPassword); |
| SetTextfieldToFocus(); |
| EXPECT_CALL(*mock_observer_, OnSubmit()).Times(1); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_RETURN); |
| } |
| |
| // Testing password textfield OnEscape Observer. |
| TEST_F(PasswordTextfieldUnitTest, OnEscapeTest) { |
| SetTextfieldToFocus(); |
| EXPECT_CALL(*mock_observer_, OnEscape()).Times(1); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_ESCAPE); |
| } |
| |
| class PinTextfieldUnitTest : public AshTestBase { |
| public: |
| PinTextfieldUnitTest() = default; |
| PinTextfieldUnitTest(const PinTextfieldUnitTest&) = delete; |
| PinTextfieldUnitTest& operator=(const PinTextfieldUnitTest&) = delete; |
| ~PinTextfieldUnitTest() override = default; |
| |
| void SetTextfieldToFocus() { |
| auth_textfield_->GetFocusManager()->SetFocusedView(auth_textfield_); |
| } |
| |
| protected: |
| // AshTestBase: |
| void SetUp() override { |
| AshTestBase::SetUp(); |
| |
| widget_ = CreateFramelessTestWidget(); |
| widget_->SetFullscreen(true); |
| |
| mock_observer_ = std::make_unique<MockAuthTextfieldObserver>(); |
| auth_textfield_ = widget_->SetContentsView( |
| std::make_unique<AuthTextfield>(AuthTextfield::AuthType::kPin)); |
| auth_textfield_->SetText(kPin); |
| auth_textfield_->AddObserver(mock_observer_.get()); |
| } |
| |
| void TearDown() override { |
| AshTestBase::TearDown(); |
| auth_textfield_->RemoveObserver(mock_observer_.get()); |
| mock_observer_.reset(); |
| auth_textfield_ = nullptr; |
| widget_.reset(); |
| } |
| |
| std::unique_ptr<views::Widget> widget_; |
| raw_ptr<AuthTextfield> auth_textfield_; |
| std::unique_ptr<MockAuthTextfieldObserver> mock_observer_; |
| }; |
| |
| // Testing PIN textfield OnContentsChanged Observer. |
| TEST_F(PinTextfieldUnitTest, OnContentsChangedTest) { |
| SetTextfieldToFocus(); |
| const std::u16string modified_pin = base::StrCat({kPin, u"5"}); |
| EXPECT_CALL(*mock_observer_, |
| OnContentsChanged(std::u16string_view(modified_pin))) |
| .Times(1); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_5); |
| } |
| |
| // Testing PIN textfield OnContentsChanged Observer with letter. |
| TEST_F(PinTextfieldUnitTest, OnContentsChangedWithLetterTest) { |
| SetTextfieldToFocus(); |
| EXPECT_CALL(*mock_observer_, OnContentsChanged(kPin)).Times(0); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_E); |
| CHECK_EQ(auth_textfield_->GetText(), kPin); |
| } |
| |
| // Testing PIN textfield InsertDigit function. |
| TEST_F(PinTextfieldUnitTest, InsertDigitTest) { |
| const std::u16string modified_pin = base::StrCat({kPin, u"5"}); |
| EXPECT_CALL(*mock_observer_, |
| OnContentsChanged(std::u16string_view(modified_pin))) |
| .Times(1); |
| auth_textfield_->InsertDigit(5); |
| } |
| |
| // Testing PIN textfield backspace press. |
| TEST_F(PinTextfieldUnitTest, BackspacePressTest) { |
| static constexpr std::u16string_view kModifiedPin = |
| kPin.substr(0, kPin.size() - 1); |
| SetTextfieldToFocus(); |
| EXPECT_CALL(*mock_observer_, OnContentsChanged(kModifiedPin)).Times(1); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_BACK); |
| } |
| |
| // Testing PIN textfield Backspace function. |
| TEST_F(PinTextfieldUnitTest, BackspaceTest) { |
| static constexpr std::u16string_view kModifiedPin = |
| kPin.substr(0, kPin.size() - 1); |
| EXPECT_CALL(*mock_observer_, OnContentsChanged(kModifiedPin)).Times(1); |
| auth_textfield_->Backspace(); |
| } |
| |
| // Testing PIN textfield OnSubmit Observer. |
| TEST_F(PinTextfieldUnitTest, OnSubmitTest) { |
| SetTextfieldToFocus(); |
| EXPECT_CALL(*mock_observer_, OnSubmit()).Times(1); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_RETURN); |
| } |
| |
| // Testing PIN textfield OnEscape Observer. |
| TEST_F(PinTextfieldUnitTest, OnEscapeTest) { |
| EXPECT_CALL(*mock_observer_, OnEscape()).Times(1); |
| SetTextfieldToFocus(); |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressAndReleaseKey(ui::VKEY_ESCAPE); |
| } |
| |
| } // namespace ash |