chromium/ash/webui/common/backend/accessibility_features_unittest.cc

// Copyright 2021 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/webui/common/backend/accessibility_features.h"

#include "ash/accessibility/accessibility_controller.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/webui/common/mojom/accessibility_features.mojom.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "chromeos/ash/components/test/ash_test_suite.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"

namespace ash {

class FakeForceHiddenElementsVisibleObserver
    : public common::mojom::ForceHiddenElementsVisibleObserver {
 public:
  FakeForceHiddenElementsVisibleObserver() = default;

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

  ~FakeForceHiddenElementsVisibleObserver() override = default;

  // common::mojom::ForceHiddenElementsVisibleObserver:
  void OnForceHiddenElementsVisibleChange(bool force_visible) override {
    is_force_visible_ = force_visible;
  }

  // Creates a pending remote that can be passed in.
  mojo::PendingRemote<common::mojom::ForceHiddenElementsVisibleObserver>
  GenerateRemote() {
    if (receiver_.is_bound())
      receiver_.reset();

    mojo::PendingRemote<common::mojom::ForceHiddenElementsVisibleObserver>
        remote;
    receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
    return remote;
  }

  bool force_visible() const { return is_force_visible_; }

  void reset_force_visible() { is_force_visible_ = false; }

 private:
  bool is_force_visible_ = false;
  mojo::Receiver<common::mojom::ForceHiddenElementsVisibleObserver> receiver_{
      this};
};

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

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

  ~AccessibilityFeaturesTest() override = default;

  // AshTestBase:
  void SetUp() override {
    ui::ResourceBundle::CleanupSharedInstance();
    AshTestSuite::LoadTestResources();
    AshTestBase::SetUp();

    accessibility_features_ = std::make_unique<AccessibilityFeatures>();
    accessibility_features_->BindInterface(
        accessibility_features_remote_.BindNewPipeAndPassReceiver());
  }

  void TearDown() override {
    accessibility_features_ = nullptr;
    AshTestBase::TearDown();
  }

 protected:
  std::unique_ptr<AccessibilityFeatures> accessibility_features_;
  FakeForceHiddenElementsVisibleObserver fake_observer_;
  mojo::Remote<common::mojom::AccessibilityFeatures>
      accessibility_features_remote_;
};

TEST_F(AccessibilityFeaturesTest, ForceVisibleObserver) {
  accessibility_features_remote_->ObserveForceHiddenElementsVisible(
      fake_observer_.GenerateRemote(),
      base::BindLambdaForTesting(
          [&](bool force_visible) { ASSERT_FALSE(force_visible); }));
  base::RunLoop().RunUntilIdle();

  // Verify the observer is initialized with |force_visible| as false.
  ASSERT_FALSE(fake_observer_.force_visible());

  AccessibilityController* accessibility_controller =
      Shell::Get()->accessibility_controller();

  // Spoken feedback.
  accessibility_controller->spoken_feedback().SetEnabled(true);
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(fake_observer_.force_visible());
  accessibility_controller->spoken_feedback().SetEnabled(false);
  fake_observer_.reset_force_visible();
  base::RunLoop().RunUntilIdle();

  // Fullscreen magnifier.
  accessibility_controller->fullscreen_magnifier().SetEnabled(true);
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(fake_observer_.force_visible());
  accessibility_controller->fullscreen_magnifier().SetEnabled(false);
  fake_observer_.reset_force_visible();
  base::RunLoop().RunUntilIdle();

  // Switch access.
  accessibility_controller->switch_access().SetEnabled(true);
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(fake_observer_.force_visible());
  accessibility_controller->switch_access().SetEnabled(false);
  fake_observer_.reset_force_visible();
  base::RunLoop().RunUntilIdle();

  // Verify enabling an unexpected accessibility feature (floating menu) does
  // not impact |force_visible|.
  accessibility_controller->floating_menu().SetEnabled(true);
  base::RunLoop().RunUntilIdle();
  ASSERT_FALSE(fake_observer_.force_visible());
}

}  // namespace ash