blob: f996dd3124c0bbc69581ec8a7f3917d286b70230 [file]
// 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 "ui/accessibility/platform/browser_accessibility_cocoa.h"
#import <Cocoa/Cocoa.h>
#include "base/test/scoped_feature_list.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/platform/ax_platform_node_unittest.h"
#include "ui/accessibility/platform/browser_accessibility_manager.h"
#include "ui/accessibility/platform/browser_accessibility_manager_mac.h"
#include "ui/accessibility/platform/test_ax_node_id_delegate.h"
namespace {
struct FeatureState {
bool mac_accessibility_api_migration_enabled = false;
};
class TestBrowserAccessibilityManager : public ui::BrowserAccessibilityManager {
public:
explicit TestBrowserAccessibilityManager(
const ui::AXTreeUpdate& initial_tree,
ui::AXNodeIdDelegate& node_id_delegate)
: BrowserAccessibilityManager(node_id_delegate, nullptr) {
Initialize(initial_tree);
}
};
class MockBrowserAccessibilityManagerMac
: public ui::BrowserAccessibilityManagerMac {
public:
MockBrowserAccessibilityManagerMac(
ui::AXTreeUpdate& update,
ui::TestAXNodeIdDelegate& node_id_delegate,
ui::AXPlatformTreeManagerDelegate* delegate)
: ui::BrowserAccessibilityManagerMac(update, node_id_delegate, delegate) {
}
MOCK_METHOD(void,
DoDefaultAction,
(const ui::BrowserAccessibility& node),
(override));
};
} // namespace
namespace ui {
// A test class for BrowserAccessibilityCocoa unit tests.
class BrowserAccessibilityCocoaTest
: public ::testing::WithParamInterface<FeatureState>,
public AXPlatformNodeTest {
public:
BrowserAccessibilityCocoaTest() {
if (GetParam().mac_accessibility_api_migration_enabled) {
base::FieldTrialParams params;
params["MacAccessibilityAPIMigrationEnabled"] = "true";
features_.InitAndEnableFeatureWithParameters(
features::kMacAccessibilityAPIMigration, params);
} else {
features_.InitAndDisableFeature(features::kMacAccessibilityAPIMigration);
}
}
private:
base::test::ScopedFeatureList features_;
};
using BrowserAccessibilityCocoaTestOldAPI = BrowserAccessibilityCocoaTest;
using BrowserAccessibilityCocoaTestNewAPI = BrowserAccessibilityCocoaTest;
// Tests that should pass regardless of new or old Cocoa a11y API.
INSTANTIATE_TEST_SUITE_P(
Common,
BrowserAccessibilityCocoaTest,
::testing::Values(
FeatureState{.mac_accessibility_api_migration_enabled = false},
FeatureState{.mac_accessibility_api_migration_enabled = true}));
/*
// Tests that should only pass with the old Cocoa a11y API.
INSTANTIATE_TEST_SUITE_P(
NoFeature,
BrowserAccessibilityCocoaTestOldAPI,
::testing::Values(FeatureState{
.mac_accessibility_api_migration_enabled = false}));
// Tests that should only pass with the new Cocoa a11y API.
INSTANTIATE_TEST_SUITE_P(MacAccessibilityAPIMigrationEnabled,
BrowserAccessibilityCocoaTestNewAPI,
::testing::Values(FeatureState{
.mac_accessibility_api_migration_enabled = true}));
*/
// Tests that accessibilityPerformAction: fires a node's default action.
TEST_P(BrowserAccessibilityCocoaTest, TestHasDefaultAction) {
AXNodeData root = AXNodeData();
root.id = 1;
root.role = ax::mojom::Role::kCheckBox;
root.SetCheckedState(ax::mojom::CheckedState::kFalse);
root.SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kCheck);
ui::AXTreeUpdate update;
update.root_id = root.id;
update.nodes.push_back(root);
ui::AXTree tree(update);
TestAXNodeIdDelegate node_id_delegate;
std::unique_ptr<MockBrowserAccessibilityManagerMac> mock_manager =
std::make_unique<MockBrowserAccessibilityManagerMac>(
update, node_id_delegate, nullptr);
std::unique_ptr<BrowserAccessibility> accessibility =
BrowserAccessibility::Create(mock_manager.get(), tree.root());
ui::AXPlatformNodeMac* platform_node = static_cast<ui::AXPlatformNodeMac*>(
AXPlatformNodeMac::GetFromUniqueId(root.id));
BrowserAccessibilityCocoa* node =
[[BrowserAccessibilityCocoa alloc] initWithObject:accessibility.get()
withPlatformNode:platform_node];
EXPECT_CALL(*mock_manager, DoDefaultAction(::testing::Ref(*accessibility)))
.Times(1);
ASSERT_EQ(accessibility->node()->data().GetCheckedState(),
ax::mojom::CheckedState::kFalse);
// TODO(https://crbug.com/406190900): Remove this deprecation pragma.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[node accessibilityPerformAction:NSAccessibilityPressAction];
#pragma clang diagnostic pop
EXPECT_EQ(accessibility->node()->data().GetCheckedState(),
ax::mojom::CheckedState::kTrue);
}
// Tests that accessibilityPerformAction: does nothing if a node has no default
// action.
TEST_P(BrowserAccessibilityCocoaTest, TestNoDefaultAction) {
AXNodeData root = AXNodeData();
root.id = 1;
root.role = ax::mojom::Role::kCheckBox;
root.SetCheckedState(ax::mojom::CheckedState::kFalse);
root.SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kNone);
ui::AXTreeUpdate update;
update.root_id = root.id;
update.nodes.push_back(root);
ui::AXTree tree(update);
TestAXNodeIdDelegate node_id_delegate;
std::unique_ptr<MockBrowserAccessibilityManagerMac> mock_manager =
std::make_unique<MockBrowserAccessibilityManagerMac>(
update, node_id_delegate, nullptr);
std::unique_ptr<BrowserAccessibility> accessibility =
BrowserAccessibility::Create(mock_manager.get(), tree.root());
ui::AXPlatformNodeMac* platform_node = static_cast<ui::AXPlatformNodeMac*>(
AXPlatformNodeMac::GetFromUniqueId(root.id));
BrowserAccessibilityCocoa* node =
[[BrowserAccessibilityCocoa alloc] initWithObject:accessibility.get()
withPlatformNode:platform_node];
EXPECT_CALL(*mock_manager, DoDefaultAction(::testing::Ref(*accessibility)))
.Times(0);
ASSERT_EQ(accessibility->node()->data().GetCheckedState(),
ax::mojom::CheckedState::kFalse);
// TODO(https://crbug.com/406190900): Remove this deprecation pragma.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[node accessibilityPerformAction:NSAccessibilityPressAction];
#pragma clang diagnostic pop
EXPECT_EQ(accessibility->node()->data().GetCheckedState(),
ax::mojom::CheckedState::kFalse);
}
// Tests that accessibilityPerformAction: does nothing if the
// BrowserAccessibility has no node.
TEST_P(BrowserAccessibilityCocoaTest, TestNoNodeForDefaultAction) {
AXNodeData root = AXNodeData();
root.id = 1;
root.role = ax::mojom::Role::kCheckBox;
root.SetCheckedState(ax::mojom::CheckedState::kFalse);
root.SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kNone);
ui::AXTreeUpdate update;
update.root_id = root.id;
update.nodes.push_back(root);
ui::AXTree tree(update);
TestAXNodeIdDelegate node_id_delegate;
std::unique_ptr<MockBrowserAccessibilityManagerMac> mock_manager =
std::make_unique<MockBrowserAccessibilityManagerMac>(
update, node_id_delegate, nullptr);
std::unique_ptr<BrowserAccessibility> accessibility =
BrowserAccessibility::Create(mock_manager.get(), tree.root());
ui::AXPlatformNodeMac* platform_node = static_cast<ui::AXPlatformNodeMac*>(
AXPlatformNodeMac::GetFromUniqueId(root.id));
BrowserAccessibilityCocoa* node =
[[BrowserAccessibilityCocoa alloc] initWithObject:accessibility.get()
withPlatformNode:platform_node];
accessibility->reset_node();
ASSERT_FALSE(accessibility->node());
EXPECT_CALL(*mock_manager, DoDefaultAction(::testing::Ref(*accessibility)))
.Times(0);
// TODO(https://crbug.com/406190900): Remove this deprecation pragma.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[node accessibilityPerformAction:NSAccessibilityPressAction];
#pragma clang diagnostic pop
}
} // namespace ui