chromium/ash/in_session_auth/auth_dialog_contents_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/in_session_auth/auth_dialog_contents_view.h"

#include "ash/in_session_auth/mock_in_session_auth_dialog_client.h"
#include "ash/login/ui/login_password_view.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/test/ash_test_base.h"
#include "base/check.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace ash {

namespace {

class AuthDialogContentsViewTest : public AshTestBase {
 public:
  AuthDialogContentsViewTest() = default;

  AuthDialogContentsViewTest(const AuthDialogContentsViewTest&) = delete;
  AuthDialogContentsViewTest& operator=(const AuthDialogContentsViewTest&) =
      delete;

  ~AuthDialogContentsViewTest() override = default;

  // AshTestBase
  void SetUp() override;
  void TearDown() override;

  std::unique_ptr<views::Widget> CreateDialogWidget(
      const display::Display& display,
      int32_t auth_methods,
      uint32_t pin_len = 0) const;

 private:
  std::unique_ptr<MockInSessionAuthDialogClient> client_;
};

void AuthDialogContentsViewTest::SetUp() {
  AshTestBase::SetUp();
  client_ = std::make_unique<MockInSessionAuthDialogClient>();
}

void AuthDialogContentsViewTest::TearDown() {
  client_.reset();
  AshTestBase::TearDown();
}

std::unique_ptr<views::Widget> AuthDialogContentsViewTest::CreateDialogWidget(
    const display::Display& display,
    int32_t auth_methods,
    uint32_t pin_len /*= 0*/) const {
  AuthDialogContentsView::AuthMethodsMetadata auth_metadata;
  auth_metadata.autosubmit_pin_length = pin_len;

  UserAvatar avatar;
  avatar.image = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
      IDR_LOGIN_DEFAULT_USER);

  std::unique_ptr<AuthDialogContentsView> dialog =
      std::make_unique<AuthDialogContentsView>(
          auth_methods, "sample_origin_name", auth_metadata, avatar);

  // Hide cursor
  AuthDialogContentsView::TestApi dialog_api(dialog.get());

  if (const raw_ptr<LoginPasswordView> password_view =
          dialog_api.GetPasswordView()) {
    views::TextfieldTestApi(
        LoginPasswordView::TestApi(password_view).textfield())
        .SetCursorLayerOpacity(0.f);
  }

  if (const raw_ptr<LoginPasswordView> pin_view =
          dialog_api.GetPinTextInputView()) {
    views::TextfieldTestApi(LoginPasswordView::TestApi(pin_view).textfield())
        .SetCursorLayerOpacity(0.f);
  }

  // Find the root window for the specified display.
  const int64_t display_id = display.id();
  aura::Window* const root_window =
      Shell::Get()->GetRootWindowForDisplayId(display_id);
  CHECK(root_window);

  // Disable mouse events to hide the mouse cursor, and to avoid
  // Ui response to mouse events (e.g hoover).
  aura::client::GetCursorClient(root_window)->DisableMouseEvents();

  views::Widget::InitParams params(
      views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET,
      views::Widget::InitParams::TYPE_POPUP);
  params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
  params.delegate = new views::WidgetDelegate();
  params.show_state = ui::SHOW_STATE_NORMAL;
  params.parent = root_window;
  params.name = "AuthDialogWidget";
  params.delegate->SetInitiallyFocusedView(dialog.get());
  params.delegate->SetOwnedByWidget(true);
  params.bounds = gfx::Rect(dialog->GetPreferredSize());

  std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>();
  widget->Init(std::move(params));
  widget->Show();
  widget->SetContentsView(std::move(dialog));

  return widget;
}

TEST_F(AuthDialogContentsViewTest, AccessibleProperties) {
  std::unique_ptr<views::Widget> widget = CreateDialogWidget(
      GetPrimaryDisplay(),
      AuthDialogContentsView::AuthMethods::kAuthPassword |
          AuthDialogContentsView::AuthMethods::kAuthFingerprint);
  AuthDialogContentsView* dialog =
      static_cast<AuthDialogContentsView*>(widget->GetContentsView());
  AuthDialogContentsView::TestApi dialog_api(
      static_cast<AuthDialogContentsView*>(dialog));
  dialog_api.PasswordOrPinAuthComplete(
      /*authenticated_by_pin=*/false, /*success=*/false, /*can_use_pin=*/false);
  ui::AXNodeData data;

  // AuthDialogContentsView accessible properties test.
  dialog->GetViewAccessibility().GetAccessibleNodeData(&data);
  EXPECT_EQ(data.role, ax::mojom::Role::kDialog);
  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
            l10n_util::GetStringFUTF16(IDS_ASH_IN_SESSION_AUTH_ACCESSIBLE_TITLE,
                                       u"sample_origin_name"));

  // FingerprintLabel accessible properties test.
  data = ui::AXNodeData();
  dialog_api.GetDialogFingerprintLabel()
      ->GetViewAccessibility()
      .GetAccessibleNodeData(&data);
  EXPECT_EQ(data.role, ax::mojom::Role::kStaticText);
}

}  // namespace

}  // namespace ash