#include "ui/accessibility/ax_node_position.h"
#include <stdint.h>
#include <algorithm>
#include <array>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_range.h"
#include "ui/accessibility/ax_selection.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/accessibility/test_single_ax_tree_manager.h"
namespace ui {
using TestPositionType = std::unique_ptr<AXPosition<AXNodePosition, AXNode>>;
using TestPositionRange = AXRange<AXPosition<AXNodePosition, AXNode>>;
namespace {
constexpr AXNodeID ROOT_ID = 1;
constexpr AXNodeID BUTTON_ID = 2;
constexpr AXNodeID CHECK_BOX_ID = 3;
constexpr AXNodeID TEXT_FIELD_ID = 4;
constexpr AXNodeID STATIC_TEXT1_ID = 5;
constexpr AXNodeID INLINE_BOX1_ID = 6;
constexpr AXNodeID LINE_BREAK_ID = 7;
constexpr AXNodeID STATIC_TEXT2_ID = 8;
constexpr AXNodeID INLINE_BOX2_ID = 9;
constexpr const auto kGraphemeClusters = std::to_array<const wchar_t*>({
L"h",
L"e",
L"y",
L"\x0939\x093F",
L"\x0928\x094D\x0926\x0940",
L"\x0E23\x0E39\x0E49",
L"\x0E2A\x0E36",
L"\x0E01",
});
class AXPositionTest : public ::testing::Test, public TestSingleAXTreeManager {
public:
AXPositionTest();
AXPositionTest(const AXPositionTest&) = delete;
AXPositionTest& operator=(const AXPositionTest&) = delete;
~AXPositionTest() override = default;
protected:
static const char* TEXT_VALUE;
void SetUp() override;
std::unique_ptr<AXTree> CreateMultipageDocument(
AXNodeData& root_data,
AXNodeData& page_1_data,
AXNodeData& page_1_text_data,
AXNodeData& page_2_data,
AXNodeData& page_2_text_data,
AXNodeData& page_3_data,
AXNodeData& page_3_text_data) const;
void CreateBrowserWindow(
AXNodeData& window,
AXNodeData& back_button,
AXNodeData& web_view,
AXNodeData& root_web_area,
AXNodeData& iframe_root,
AXNodeData& paragraph,
AXNodeData& address_bar,
std::vector<TestSingleAXTreeManager>& out_managers) const;
std::unique_ptr<AXTree> CreateMultilingualDocument(
std::vector<int>* text_offsets) const;
void AssertTextLengthEquals(const AXNodeID& node_id,
int expected_text_length) const;
std::unique_ptr<AXTree> CreateAXTree(
const std::vector<AXNodeData>& nodes,
const AXTreeID& parent_tree_id = AXTreeID()) const;
AXNodeData root_;
AXNodeData button_;
AXNodeData check_box_;
AXNodeData text_field_;
AXNodeData static_text1_;
AXNodeData line_break_;
AXNodeData static_text2_;
AXNodeData inline_box1_;
AXNodeData inline_box2_;
private:
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behaviour_;
TestSingleAXTreeManager views_tree_manager_;
};
struct ExpandToEnclosingTextBoundaryTestParam {
ax::mojom::TextBoundary boundary;
AXRangeExpandBehavior expand_behavior;
std::string expected_anchor_position;
std::string expected_focus_position;
};
class AXPositionExpandToEnclosingTextBoundaryTestWithParam
: public AXPositionTest,
public ::testing::WithParamInterface<
ExpandToEnclosingTextBoundaryTestParam> {
public:
AXPositionExpandToEnclosingTextBoundaryTestWithParam() = default;
AXPositionExpandToEnclosingTextBoundaryTestWithParam(
const AXPositionExpandToEnclosingTextBoundaryTestWithParam&) = delete;
AXPositionExpandToEnclosingTextBoundaryTestWithParam& operator=(
const AXPositionExpandToEnclosingTextBoundaryTestWithParam&) = delete;
~AXPositionExpandToEnclosingTextBoundaryTestWithParam() override = default;
};
struct CreatePositionAtTextBoundaryTestParam {
ax::mojom::TextBoundary boundary;
ax::mojom::MoveDirection direction;
AXMovementOptions movement_options;
std::string expected_text_position;
};
class AXPositionCreatePositionAtTextBoundaryTestWithParam
: public AXPositionTest,
public ::testing::WithParamInterface<
CreatePositionAtTextBoundaryTestParam> {
public:
AXPositionCreatePositionAtTextBoundaryTestWithParam() = default;
AXPositionCreatePositionAtTextBoundaryTestWithParam(
const AXPositionCreatePositionAtTextBoundaryTestWithParam&) = delete;
AXPositionCreatePositionAtTextBoundaryTestWithParam& operator=(
const AXPositionCreatePositionAtTextBoundaryTestWithParam&) = delete;
~AXPositionCreatePositionAtTextBoundaryTestWithParam() override = default;
};
struct TextNavigationTestParam {
base::RepeatingCallback<TestPositionType(const TestPositionType&)> TestMethod;
AXNodeID start_node_id;
int start_offset;
std::vector<std::string> expectations;
bool upstream_is_not_moved = false;
};
class AXPositionTextNavigationTestWithParam
: public AXPositionTest,
public ::testing::WithParamInterface<TextNavigationTestParam> {
public:
AXPositionTextNavigationTestWithParam() = default;
AXPositionTextNavigationTestWithParam(
const AXPositionTextNavigationTestWithParam&) = delete;
AXPositionTextNavigationTestWithParam& operator=(
const AXPositionTextNavigationTestWithParam&) = delete;
~AXPositionTextNavigationTestWithParam() override = default;
};
AXPositionTest::AXPositionTest()
: ax_embedded_object_behaviour_(
AXEmbeddedObjectBehavior::kSuppressCharacter) {}
const char* AXPositionTest::TEXT_VALUE = "Line 1\nLine 2";
void AXPositionTest::SetUp() {
AXNodeData window;
window.id = 1;
window.role = ax::mojom::Role::kWindow;
window.SetName("Test page - Google Chrome");
window.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"BrowserRootView");
AXNodeData non_client_view;
non_client_view.id = 2;
non_client_view.role = ax::mojom::Role::kClient;
non_client_view.SetName("Google Chrome");
non_client_view.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"NonClientView");
window.child_ids = {non_client_view.id};
AXNodeData web_view;
web_view.id = 3;
web_view.role = ax::mojom::Role::kWebView;
web_view.AddState(ax::mojom::State::kInvisible);
web_view.SetNameExplicitlyEmpty();
web_view.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"WebView");
non_client_view.child_ids = {web_view.id};
std::unique_ptr<AXTree> views_tree =
CreateAXTree({window, non_client_view, web_view});
root_.id = ROOT_ID;
button_.id = BUTTON_ID;
check_box_.id = CHECK_BOX_ID;
text_field_.id = TEXT_FIELD_ID;
static_text1_.id = STATIC_TEXT1_ID;
inline_box1_.id = INLINE_BOX1_ID;
line_break_.id = LINE_BREAK_ID;
static_text2_.id = STATIC_TEXT2_ID;
inline_box2_.id = INLINE_BOX2_ID;
root_.role = ax::mojom::Role::kRootWebArea;
root_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
button_.role = ax::mojom::Role::kButton;
button_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
button_.SetHasPopup(ax::mojom::HasPopup::kMenu);
button_.SetName("Button");
button_.SetNameFrom(ax::mojom::NameFrom::kAttribute);
button_.relative_bounds.bounds = gfx::RectF(20, 20, 200, 30);
root_.child_ids.push_back(button_.id);
check_box_.role = ax::mojom::Role::kCheckBox;
check_box_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
check_box_.SetCheckedState(ax::mojom::CheckedState::kTrue);
check_box_.SetName("Check box");
check_box_.SetNameFrom(ax::mojom::NameFrom::kAttribute);
check_box_.relative_bounds.bounds = gfx::RectF(20, 50, 200, 30);
root_.child_ids.push_back(check_box_.id);
text_field_.role = ax::mojom::Role::kTextField;
text_field_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
text_field_.AddState(ax::mojom::State::kEditable);
text_field_.SetValue(TEXT_VALUE);
text_field_.AddIntListAttribute(ax::mojom::IntListAttribute::kLineStarts,
std::vector<int32_t>{0, 7});
text_field_.child_ids.push_back(static_text1_.id);
text_field_.child_ids.push_back(line_break_.id);
text_field_.child_ids.push_back(static_text2_.id);
root_.child_ids.push_back(text_field_.id);
static_text1_.role = ax::mojom::Role::kStaticText;
static_text1_.AddState(ax::mojom::State::kEditable);
static_text1_.SetName("Line 1");
static_text1_.child_ids.push_back(inline_box1_.id);
static_text1_.AddIntAttribute(
ax::mojom::IntAttribute::kTextStyle,
static_cast<int32_t>(ax::mojom::TextStyle::kBold));
inline_box1_.role = ax::mojom::Role::kInlineTextBox;
inline_box1_.AddState(ax::mojom::State::kEditable);
inline_box1_.SetName("Line 1");
inline_box1_.AddIntListAttribute(ax::mojom::IntListAttribute::kSentenceStarts,
{0});
inline_box1_.AddIntListAttribute(ax::mojom::IntListAttribute::kSentenceEnds,
{6});
inline_box1_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0, 5});
inline_box1_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{4, 6});
inline_box1_.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
line_break_.id);
line_break_.role = ax::mojom::Role::kLineBreak;
line_break_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
line_break_.AddState(ax::mojom::State::kEditable);
line_break_.SetName("\n");
line_break_.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box1_.id);
static_text2_.role = ax::mojom::Role::kStaticText;
static_text2_.AddState(ax::mojom::State::kEditable);
static_text2_.SetName("Line 2");
static_text2_.child_ids.push_back(inline_box2_.id);
static_text2_.AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize, 1.0f);
inline_box2_.role = ax::mojom::Role::kInlineTextBox;
inline_box2_.AddState(ax::mojom::State::kEditable);
inline_box2_.SetName("Line 2");
inline_box2_.AddIntListAttribute(ax::mojom::IntListAttribute::kSentenceStarts,
{0});
inline_box2_.AddIntListAttribute(ax::mojom::IntListAttribute::kSentenceEnds,
{6});
inline_box2_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0, 5});
inline_box2_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{4, 6});
AXTreeUpdate initial_state;
initial_state.root_id = 1;
initial_state.nodes = {root_, button_, check_box_,
text_field_, static_text1_, inline_box1_,
line_break_, static_text2_, inline_box2_};
initial_state.has_tree_data = true;
initial_state.tree_data.tree_id = AXTreeID::CreateNewAXTreeID();
initial_state.tree_data.parent_tree_id = views_tree->GetAXTreeID();
initial_state.tree_data.title = "Dialog title";
SetTree(std::make_unique<AXTree>(initial_state));
AXTreeUpdate views_tree_update;
web_view.AddChildTreeId(GetTreeID());
views_tree_update.nodes = {web_view};
ASSERT_TRUE(views_tree->Unserialize(views_tree_update));
views_tree_manager_ = TestSingleAXTreeManager(std::move(views_tree));
}
std::unique_ptr<AXTree> AXPositionTest::CreateMultipageDocument(
AXNodeData& root_data,
AXNodeData& page_1_data,
AXNodeData& page_1_text_data,
AXNodeData& page_2_data,
AXNodeData& page_2_text_data,
AXNodeData& page_3_data,
AXNodeData& page_3_text_data) const {
root_data.id = 1;
root_data.role = ax::mojom::Role::kPdfRoot;
page_1_data.id = 2;
page_1_data.role = ax::mojom::Role::kRegion;
page_1_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsPageBreakingObject,
true);
page_1_text_data.id = 3;
page_1_text_data.role = ax::mojom::Role::kStaticText;
page_1_text_data.SetName("some text on page 1");
page_1_text_data.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
page_1_data.child_ids = {3};
page_2_data.id = 4;
page_2_data.role = ax::mojom::Role::kRegion;
page_2_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsPageBreakingObject,
true);
page_2_text_data.id = 5;
page_2_text_data.role = ax::mojom::Role::kStaticText;
page_2_text_data.SetName("some text on page 2");
page_2_text_data.AddIntAttribute(
ax::mojom::IntAttribute::kTextStyle,
static_cast<int32_t>(ax::mojom::TextStyle::kBold));
page_2_data.child_ids = {5};
page_3_data.id = 6;
page_3_data.role = ax::mojom::Role::kRegion;
page_3_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsPageBreakingObject,
true);
page_3_text_data.id = 7;
page_3_text_data.role = ax::mojom::Role::kStaticText;
page_3_text_data.SetName("some more text on page 3");
page_3_data.child_ids = {7};
root_data.child_ids = {2, 4, 6};
return CreateAXTree({root_data, page_1_data, page_1_text_data, page_2_data,
page_2_text_data, page_3_data, page_3_text_data});
}
void AXPositionTest::CreateBrowserWindow(
AXNodeData& window,
AXNodeData& back_button,
AXNodeData& web_view,
AXNodeData& root_web_area,
AXNodeData& iframe_root,
AXNodeData& paragraph,
AXNodeData& address_bar,
std::vector<TestSingleAXTreeManager>& out_managers) const {
window.id = 1;
window.role = ax::mojom::Role::kWindow;
window.SetName("Test page - Google Chrome");
window.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"BrowserRootView");
AXNodeData non_client_view;
non_client_view.id = 2;
non_client_view.role = ax::mojom::Role::kClient;
non_client_view.SetName("Google Chrome");
non_client_view.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"NonClientView");
window.child_ids = {non_client_view.id};
AXNodeData browser_view;
browser_view.id = 3;
browser_view.role = ax::mojom::Role::kClient;
browser_view.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"BrowserView");
AXNodeData toolbar;
toolbar.id = 4;
toolbar.role = ax::mojom::Role::kPane;
toolbar.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"ToolbarView");
browser_view.child_ids = {toolbar.id};
back_button.id = 5;
back_button.role = ax::mojom::Role::kButton;
back_button.AddState(ax::mojom::State::kFocusable);
back_button.SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kPress);
back_button.SetHasPopup(ax::mojom::HasPopup::kMenu);
back_button.SetName("Back");
back_button.SetNameFrom(ax::mojom::NameFrom::kContents);
back_button.SetDescription("Press to go back, context menu to see history");
back_button.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"ToolbarButton");
back_button.AddAction(ax::mojom::Action::kShowContextMenu);
toolbar.child_ids = {back_button.id};
web_view.id = 6;
web_view.role = ax::mojom::Role::kWebView;
web_view.AddState(ax::mojom::State::kInvisible);
web_view.SetNameExplicitlyEmpty();
web_view.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"WebView");
address_bar.id = 7;
address_bar.role = ax::mojom::Role::kTextField;
address_bar.SetName("Address and search bar");
address_bar.SetNameFrom(ax::mojom::NameFrom::kAttribute);
address_bar.SetValue("test.com");
address_bar.AddStringAttribute(ax::mojom::StringAttribute::kAutoComplete,
"both");
address_bar.AddStringAttribute(ax::mojom::StringAttribute::kClassName,
"OmniboxViewViews");
address_bar.AddAction(ax::mojom::Action::kShowContextMenu);
non_client_view.child_ids = {browser_view.id, web_view.id, address_bar.id};
root_web_area.id = 1;
root_web_area.role = ax::mojom::Role::kRootWebArea;
root_web_area.AddState(ax::mojom::State::kFocusable);
root_web_area.SetName("Test page");
root_web_area.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData iframe;
iframe.id = 2;
iframe.role = ax::mojom::Role::kIframe;
iframe.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph.id = 3;
paragraph.role = ax::mojom::Role::kParagraph;
paragraph.SetName("After iframe");
paragraph.SetNameFrom(ax::mojom::NameFrom::kContents);
paragraph.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
root_web_area.child_ids = {iframe.id, paragraph.id};
iframe_root.id = 1;
iframe_root.role = ax::mojom::Role::kRootWebArea;
iframe_root.AddState(ax::mojom::State::kFocusable);
iframe_root.SetName("Inside iframe");
iframe_root.SetNameFrom(ax::mojom::NameFrom::kContents);
iframe_root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
std::unique_ptr<AXTree> views_tree =
CreateAXTree({window, non_client_view, browser_view, toolbar, back_button,
web_view, address_bar});
std::unique_ptr<AXTree> webpage_tree = CreateAXTree(
{root_web_area, iframe, paragraph}, views_tree->GetAXTreeID());
std::unique_ptr<AXTree> iframe_tree =
CreateAXTree({iframe_root}, webpage_tree->GetAXTreeID());
AXTreeUpdate views_tree_update;
web_view.AddChildTreeId(webpage_tree->GetAXTreeID());
views_tree_update.nodes = {web_view};
ASSERT_TRUE(views_tree->Unserialize(views_tree_update));
AXTreeUpdate webpage_tree_update;
iframe.AddChildTreeId(iframe_tree->GetAXTreeID());
webpage_tree_update.nodes = {iframe};
ASSERT_TRUE(webpage_tree->Unserialize(webpage_tree_update));
out_managers.emplace_back(std::move(views_tree));
out_managers.emplace_back(std::move(webpage_tree));
out_managers.emplace_back(std::move(iframe_tree));
}
std::unique_ptr<AXTree> AXPositionTest::CreateMultilingualDocument(
std::vector<int>* text_offsets) const {
EXPECT_NE(nullptr, text_offsets);
text_offsets->push_back(0);
std::u16string english_text;
for (int i = 0; i < 3; ++i) {
std::u16string grapheme = base::WideToUTF16(kGraphemeClusters[i]);
EXPECT_EQ(1u, grapheme.length())
<< "All English characters should be one UTF16 code unit in length.";
text_offsets->push_back(text_offsets->back() +
static_cast<int>(grapheme.length()));
english_text.append(grapheme);
}
std::u16string hindi_text;
for (int i = 3; i < 5; ++i) {
std::u16string grapheme = base::WideToUTF16(kGraphemeClusters[i]);
EXPECT_LE(2u, grapheme.length()) << "All Hindi characters should be two "
"or more UTF16 code units in length.";
text_offsets->push_back(text_offsets->back() +
static_cast<int>(grapheme.length()));
hindi_text.append(grapheme);
}
std::u16string thai_text;
for (int i = 5; i < 8; ++i) {
std::u16string grapheme = base::WideToUTF16(kGraphemeClusters[i]);
EXPECT_LT(0u, grapheme.length())
<< "One of the Thai characters should be one UTF16 code unit, "
"whilst others should be two or more.";
text_offsets->push_back(text_offsets->back() +
static_cast<int>(grapheme.length()));
thai_text.append(grapheme);
}
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_data1;
text_data1.id = 2;
text_data1.role = ax::mojom::Role::kStaticText;
text_data1.SetName(english_text);
AXNodeData text_data2;
text_data2.id = 3;
text_data2.role = ax::mojom::Role::kStaticText;
text_data2.SetName(hindi_text);
AXNodeData text_data3;
text_data3.id = 4;
text_data3.role = ax::mojom::Role::kStaticText;
text_data3.SetName(thai_text);
root_data.child_ids = {text_data1.id, text_data2.id, text_data3.id};
return CreateAXTree({root_data, text_data1, text_data2, text_data3});
}
void AXPositionTest::AssertTextLengthEquals(const AXNodeID& node_id,
int expected_text_length) const {
TestPositionType text_position = CreateTextPosition(
node_id, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(expected_text_length, text_position->MaxTextOffset());
ASSERT_EQ(expected_text_length,
static_cast<int>(text_position->GetText().length()));
}
std::unique_ptr<AXTree> AXPositionTest::CreateAXTree(
const std::vector<AXNodeData>& nodes,
const AXTreeID& parent_tree_id) const {
EXPECT_FALSE(nodes.empty());
AXTreeUpdate update;
update.tree_data.tree_id = AXTreeID::CreateNewAXTreeID();
update.tree_data.parent_tree_id = parent_tree_id;
update.has_tree_data = true;
update.root_id = nodes[0].id;
update.nodes = nodes;
return std::make_unique<AXTree>(update);
}
}
TEST_F(AXPositionTest, DISABLED_Clone) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType copy_position = null_position->Clone();
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsNullPosition());
EXPECT_EQ(kInvalidAXNodeID, copy_position->anchor_id());
EXPECT_EQ(AXNodePosition::INVALID_INDEX, copy_position->child_index());
EXPECT_EQ(AXNodePosition::INVALID_OFFSET, copy_position->text_offset());
TestPositionType tree_position =
CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, tree_position);
copy_position = tree_position->Clone();
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTreePosition());
EXPECT_EQ(root_.id, copy_position->anchor_id());
EXPECT_EQ(0, copy_position->child_index());
EXPECT_EQ(AXNodePosition::INVALID_OFFSET, copy_position->text_offset());
tree_position = CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
copy_position = tree_position->Clone();
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTreePosition());
EXPECT_EQ(root_.id, copy_position->anchor_id());
EXPECT_EQ(1, copy_position->child_index());
EXPECT_EQ(AXNodePosition::INVALID_OFFSET, copy_position->text_offset());
EXPECT_DEATH_IF_SUPPORTED(
CreateTreePosition(root_, AXNodePosition::BEFORE_TEXT),
"Creating invalid positions is disallowed.");
TestPositionType text_position = CreateTextPosition(
text_field_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
copy_position = text_position->Clone();
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTextPosition());
EXPECT_EQ(text_field_.id, copy_position->anchor_id());
EXPECT_EQ(0, copy_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, copy_position->affinity());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
copy_position = text_position->Clone();
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTextPosition());
EXPECT_EQ(text_field_.id, copy_position->anchor_id());
EXPECT_EQ(0, copy_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, copy_position->affinity());
EXPECT_EQ(AXNodePosition::INVALID_INDEX, copy_position->child_index());
}
TEST_F(AXPositionTest, Serialize) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType copy_position =
AXNodePosition::Unserialize(null_position->Serialize());
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsNullPosition());
TestPositionType tree_position =
CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
copy_position = AXNodePosition::Unserialize(tree_position->Serialize());
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTreePosition());
EXPECT_EQ(root_.id, copy_position->anchor_id());
EXPECT_EQ(1, copy_position->child_index());
EXPECT_EQ(AXNodePosition::INVALID_OFFSET, copy_position->text_offset());
tree_position = CreateTreePosition(inline_box2_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, tree_position);
copy_position = AXNodePosition::Unserialize(tree_position->Serialize());
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTreePosition());
EXPECT_EQ(inline_box2_.id, copy_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, copy_position->child_index());
EXPECT_EQ(AXNodePosition::INVALID_OFFSET, copy_position->text_offset());
TestPositionType text_position = CreateTextPosition(
text_field_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
copy_position = AXNodePosition::Unserialize(text_position->Serialize());
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTextPosition());
EXPECT_EQ(text_field_.id, copy_position->anchor_id());
EXPECT_EQ(0, copy_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, copy_position->affinity());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
copy_position = AXNodePosition::Unserialize(text_position->Serialize());
ASSERT_NE(nullptr, copy_position);
EXPECT_TRUE(copy_position->IsTextPosition());
EXPECT_EQ(text_field_.id, copy_position->anchor_id());
EXPECT_EQ(0, copy_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, copy_position->affinity());
EXPECT_EQ(AXNodePosition::INVALID_INDEX, copy_position->child_index());
}
TEST_F(AXPositionTest, ToString) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData static_text_data_1;
static_text_data_1.id = 2;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.SetName("some text");
AXNodeData static_text_data_2;
static_text_data_2.id = 3;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName(u"\xfffc");
AXNodeData static_text_data_3;
static_text_data_3.id = 4;
static_text_data_3.role = ax::mojom::Role::kStaticText;
static_text_data_3.SetName("more text");
root_data.child_ids = {static_text_data_1.id, static_text_data_2.id,
static_text_data_3.id};
SetTree(CreateAXTree(
{root_data, static_text_data_1, static_text_data_2, static_text_data_3}));
TestPositionType text_position_1 = CreateTextPosition(
root_data, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_1->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=1 text_offset=0 affinity=downstream "
"annotated_text=<s>ome text\xEF\xBF\xBCmore text",
text_position_1->ToString());
TestPositionType text_position_2 = CreateTextPosition(
root_data, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_2->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=1 text_offset=5 affinity=downstream "
"annotated_text=some <t>ext\xEF\xBF\xBCmore text",
text_position_2->ToString());
TestPositionType text_position_3 = CreateTextPosition(
root_data, 9 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_3->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=1 text_offset=9 affinity=downstream "
"annotated_text=some text<\xEF\xBF\xBC>more text",
text_position_3->ToString());
TestPositionType text_position_4 = CreateTextPosition(
root_data, 10 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_4->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=1 text_offset=10 affinity=downstream "
"annotated_text=some text\xEF\xBF\xBC<m>ore text",
text_position_4->ToString());
TestPositionType text_position_5 = CreateTextPosition(
root_data, 19 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_5->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=1 text_offset=19 affinity=downstream "
"annotated_text=some text\xEF\xBF\xBCmore text<>",
text_position_5->ToString());
TestPositionType text_position_6 =
CreateTextPosition(static_text_data_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_6->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=3 text_offset=0 affinity=downstream "
"annotated_text=<\xEF\xBF\xBC>",
text_position_6->ToString());
TestPositionType text_position_7 =
CreateTextPosition(static_text_data_2, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_7->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=3 text_offset=1 affinity=downstream "
"annotated_text=\xEF\xBF\xBC<>",
text_position_7->ToString());
TestPositionType text_position_8 =
CreateTextPosition(static_text_data_3, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_8->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=4 text_offset=0 affinity=downstream "
"annotated_text=<m>ore text",
text_position_8->ToString());
TestPositionType text_position_9 =
CreateTextPosition(static_text_data_3, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_9->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=4 text_offset=5 affinity=downstream "
"annotated_text=more <t>ext",
text_position_9->ToString());
TestPositionType text_position_10 =
CreateTextPosition(static_text_data_3, 9 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_10->IsTextPosition());
EXPECT_EQ(
"TextPosition anchor_id=4 text_offset=9 affinity=downstream "
"annotated_text=more text<>",
text_position_10->ToString());
}
TEST_F(AXPositionTest, DISABLED_IsIgnored) {
EXPECT_FALSE(AXNodePosition::CreateNullPosition()->IsIgnored());
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData static_text_data_1;
static_text_data_1.id = 2;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.SetName("One");
static_text_data_1.AddState(ax::mojom::State::kIgnored);
AXNodeData inline_box_data_1;
inline_box_data_1.id = 3;
inline_box_data_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_1.SetName("One");
inline_box_data_1.AddState(ax::mojom::State::kIgnored);
AXNodeData container_data;
container_data.id = 4;
container_data.role = ax::mojom::Role::kGenericContainer;
container_data.AddState(ax::mojom::State::kIgnored);
AXNodeData static_text_data_2;
static_text_data_2.id = 5;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName("Two");
AXNodeData inline_box_data_2;
inline_box_data_2.id = 6;
inline_box_data_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_2.SetName("Two");
static_text_data_1.child_ids = {inline_box_data_1.id};
container_data.child_ids = {static_text_data_2.id};
static_text_data_2.child_ids = {inline_box_data_2.id};
root_data.child_ids = {static_text_data_1.id, container_data.id};
SetTree(
CreateAXTree({root_data, static_text_data_1, inline_box_data_1,
container_data, static_text_data_2, inline_box_data_2}));
TestPositionType text_position_3 = CreateTextPosition(
root_data, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_3->IsTextPosition());
EXPECT_FALSE(text_position_3->IsIgnored());
TestPositionType text_position_4 = CreateTextPosition(
root_data, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_4->IsTextPosition());
EXPECT_FALSE(text_position_4->IsIgnored());
TestPositionType text_position_5 =
CreateTextPosition(container_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_5->IsTextPosition());
EXPECT_TRUE(text_position_5->IsIgnored());
TestPositionType text_position_6 =
CreateTextPosition(static_text_data_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_6->IsTextPosition());
EXPECT_FALSE(text_position_6->IsIgnored());
TestPositionType text_position_7 =
CreateTextPosition(inline_box_data_1, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position_7->IsTextPosition());
EXPECT_TRUE(text_position_7->IsIgnored());
TestPositionType tree_position_1 =
CreateTreePosition(root_data, 0 );
ASSERT_TRUE(tree_position_1->IsTreePosition());
EXPECT_TRUE(tree_position_1->IsIgnored());
TestPositionType tree_position_2 =
CreateTreePosition(root_data, 1 );
ASSERT_TRUE(tree_position_2->IsTreePosition());
EXPECT_TRUE(tree_position_2->IsIgnored());
TestPositionType tree_position_3 =
CreateTreePosition(inline_box_data_1, 0 );
ASSERT_TRUE(tree_position_3->IsTreePosition());
EXPECT_TRUE(tree_position_3->IsIgnored());
TestPositionType tree_position_4 =
CreateTreePosition(inline_box_data_1, AXNodePosition::BEFORE_TEXT);
ASSERT_TRUE(tree_position_4->IsTreePosition());
EXPECT_TRUE(tree_position_4->IsIgnored());
TestPositionType tree_position_5 =
CreateTreePosition(root_data, 2 );
ASSERT_TRUE(tree_position_5->IsTreePosition());
EXPECT_TRUE(tree_position_5->IsIgnored());
EXPECT_DEATH_IF_SUPPORTED(
CreateTreePosition(static_text_data_1, AXNodePosition::BEFORE_TEXT),
"Creating invalid positions is disallowed.");
}
TEST_F(AXPositionTest, GetTextFromNullPosition) {
TestPositionType text_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsNullPosition());
ASSERT_EQ(u"", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromRoot) {
TestPositionType text_position = CreateTextPosition(
root_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"Line 1\nLine 2", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromButton) {
TestPositionType text_position = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromCheckbox) {
TestPositionType text_position = CreateTextPosition(
check_box_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromTextField) {
TestPositionType text_position = CreateTextPosition(
text_field_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"Line 1\nLine 2", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromStaticText) {
TestPositionType text_position = CreateTextPosition(
static_text1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"Line 1", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromInlineTextBox) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"Line 1", text_position->GetText());
}
TEST_F(AXPositionTest, GetTextFromLineBreak) {
TestPositionType text_position = CreateTextPosition(
line_break_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(u"\n", text_position->GetText());
}
TEST_F(AXPositionTest, IsInLineBreak) {
TestPositionType text_field_position = CreateTextPosition(
text_field_, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_field_position);
EXPECT_FALSE(text_field_position->IsPointingToLineBreak());
TestPositionType static_text1_position = CreateTextPosition(
static_text1_, 6 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, static_text1_position);
EXPECT_FALSE(static_text1_position->IsPointingToLineBreak());
text_field_position = CreateTextPosition(
text_field_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_field_position);
EXPECT_TRUE(text_field_position->IsPointingToLineBreak());
text_field_position = CreateTextPosition(
text_field_, 7 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_field_position);
EXPECT_FALSE(text_field_position->IsPointingToLineBreak());
text_field_position = CreateTextPosition(text_field_, 7 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_field_position);
EXPECT_TRUE(text_field_position->IsPointingToLineBreak());
TestPositionType line_break_position = CreateTextPosition(
line_break_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, line_break_position);
EXPECT_TRUE(line_break_position->IsPointingToLineBreak());
line_break_position = CreateTextPosition(
line_break_, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, line_break_position);
EXPECT_TRUE(line_break_position->IsPointingToLineBreak());
line_break_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, line_break_position);
EXPECT_TRUE(line_break_position->IsPointingToLineBreak());
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_field_data;
text_field_data.id = 2;
text_field_data.role = ax::mojom::Role::kTextField;
text_field_data.SetValue(" \n");
root_data.child_ids = {text_field_data.id};
SetTree(CreateAXTree({root_data, text_field_data}));
TestPositionType root_data_position = CreateTextPosition(
root_data, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, root_data_position);
EXPECT_FALSE(root_data_position->IsPointingToLineBreak());
root_data_position = CreateTextPosition(root_data, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, root_data_position);
EXPECT_TRUE(root_data_position->IsPointingToLineBreak());
root_data_position = CreateTextPosition(root_data, 2 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, root_data_position);
EXPECT_FALSE(root_data_position->IsPointingToLineBreak());
}
TEST_F(AXPositionTest, IsInWhiteSpace) {
TestPositionType button_position = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, button_position);
EXPECT_FALSE(button_position->IsInWhiteSpace())
<< "Positions anchored to nodes with no text in them should not be "
"classified as 'in white space'.";
TestPositionType text_field_position = CreateTextPosition(
text_field_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_field_position);
EXPECT_FALSE(text_field_position->IsInWhiteSpace());
TestPositionType line_break_position = CreateTextPosition(
line_break_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, line_break_position);
EXPECT_TRUE(line_break_position->IsInWhiteSpace());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromNullPosition) {
TestPositionType text_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsNullPosition());
ASSERT_EQ(AXNodePosition::INVALID_OFFSET, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromRoot) {
TestPositionType text_position = CreateTextPosition(
root_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(13, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromButton) {
TestPositionType text_position = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(0, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromCheckbox) {
TestPositionType text_position = CreateTextPosition(
check_box_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(0, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromTextfield) {
TestPositionType text_position = CreateTextPosition(
text_field_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(13, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromStaticText) {
TestPositionType text_position = CreateTextPosition(
static_text1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(6, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromInlineTextBox) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(6, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetFromLineBreak) {
TestPositionType text_position = CreateTextPosition(
line_break_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(1, text_position->MaxTextOffset());
}
TEST_F(AXPositionTest, GetMaxTextOffsetUpdate) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_field_data;
text_field_data.id = 2;
text_field_data.role = ax::mojom::Role::kTextField;
text_field_data.SetName("some text");
text_field_data.SetNameFrom(ax::mojom::NameFrom::kPlaceholder);
AXNodeData text_data;
text_data.id = 3;
text_data.role = ax::mojom::Role::kStaticText;
text_data.SetName("more text");
text_data.SetNameFrom(ax::mojom::NameFrom::kContents);
root_data.child_ids = {text_field_data.id, text_data.id};
SetTree(CreateAXTree({root_data, text_field_data, text_data}));
AssertTextLengthEquals(text_field_data.id, 9);
AssertTextLengthEquals(text_data.id, 9);
AssertTextLengthEquals(root_data.id, 18);
text_field_data.SetName("Adjusted line 1");
SetTree(CreateAXTree({root_data, text_field_data, text_data}));
AssertTextLengthEquals(text_field_data.id, 15);
AssertTextLengthEquals(text_data.id, 9);
AssertTextLengthEquals(root_data.id, 24);
text_field_data.SetValue("Value should override name");
SetTree(CreateAXTree({root_data, text_field_data, text_data}));
AssertTextLengthEquals(text_field_data.id, 26);
AssertTextLengthEquals(text_data.id, 9);
AssertTextLengthEquals(root_data.id, 35);
text_field_data.SetValue("");
SetTree(CreateAXTree({root_data, text_field_data, text_data}));
AssertTextLengthEquals(text_field_data.id, 15);
AssertTextLengthEquals(text_data.id, 9);
AssertTextLengthEquals(root_data.id, 24);
}
TEST_F(AXPositionTest, GetMaxTextOffsetAndGetTextWithGeneratedContent) {
AXNodeData root_1;
AXNodeData text_field_2;
AXNodeData static_text_3;
AXNodeData inline_box_4;
AXNodeData static_text_5;
AXNodeData inline_box_6;
root_1.id = 1;
text_field_2.id = 2;
static_text_3.id = 3;
inline_box_4.id = 4;
static_text_5.id = 5;
inline_box_6.id = 6;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {text_field_2.id};
text_field_2.role = ax::mojom::Role::kTextField;
text_field_2.SetValue("3.14");
text_field_2.child_ids = {static_text_3.id, static_text_5.id};
static_text_3.role = ax::mojom::Role::kStaticText;
static_text_3.SetName("Placeholder from generated content");
static_text_3.child_ids = {inline_box_4.id};
inline_box_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_4.SetName("Placeholder from generated content");
static_text_5.role = ax::mojom::Role::kStaticText;
static_text_5.SetName("3.14");
static_text_5.child_ids = {inline_box_6.id};
inline_box_6.role = ax::mojom::Role::kInlineTextBox;
inline_box_6.SetName("3.14");
SetTree(CreateAXTree({root_1, text_field_2, static_text_3, inline_box_4,
static_text_5, inline_box_6}));
TestPositionType text_position = CreateTextPosition(
text_field_2, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(38, text_position->MaxTextOffset());
EXPECT_EQ(u"Placeholder from generated content3.14",
text_position->GetText());
}
TEST_F(AXPositionTest, AtStartOfAnchorWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
EXPECT_FALSE(null_position->AtStartOfAnchor());
}
TEST_F(AXPositionTest, AtStartOfAnchorWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, tree_position);
EXPECT_TRUE(tree_position->AtStartOfAnchor());
tree_position = CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
EXPECT_FALSE(tree_position->AtStartOfAnchor());
tree_position = CreateTreePosition(root_, 3 );
ASSERT_NE(nullptr, tree_position);
EXPECT_FALSE(tree_position->AtStartOfAnchor());
tree_position = CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, tree_position);
EXPECT_TRUE(tree_position->AtStartOfAnchor());
tree_position = CreateTreePosition(inline_box1_, 0 );
ASSERT_NE(nullptr, tree_position);
EXPECT_FALSE(tree_position->AtStartOfAnchor());
}
TEST_F(AXPositionTest, AtStartOfAnchorWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfAnchor());
text_position = CreateTextPosition(inline_box1_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfAnchor());
text_position = CreateTextPosition(inline_box1_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfAnchor());
}
TEST_F(AXPositionTest, AtEndOfAnchorWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
EXPECT_FALSE(null_position->AtEndOfAnchor());
}
TEST_F(AXPositionTest, AtEndOfAnchorWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 3 );
ASSERT_NE(nullptr, tree_position);
EXPECT_TRUE(tree_position->AtEndOfAnchor());
tree_position = CreateTreePosition(root_, 2 );
ASSERT_NE(nullptr, tree_position);
EXPECT_FALSE(tree_position->AtEndOfAnchor());
tree_position = CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, tree_position);
EXPECT_FALSE(tree_position->AtEndOfAnchor());
}
TEST_F(AXPositionTest, AtEndOfAnchorWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfAnchor());
text_position = CreateTextPosition(inline_box1_, 5 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfAnchor());
text_position = CreateTextPosition(inline_box1_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfAnchor());
}
TEST_F(AXPositionTest, AtStartOfLineWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
text_position = CreateTextPosition(inline_box1_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfLine());
text_position = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfLine());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
text_position = CreateTextPosition(inline_box2_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfLine());
}
TEST_F(AXPositionTest, AtStartOfLineStaticTextExtraPrecedingSpace) {
AXNodeData root;
root.id = 1;
root.role = ax::mojom::Role::kRootWebArea;
root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData label_text;
label_text.id = 2;
label_text.role = ax::mojom::Role::kLabelText;
AXNodeData static_text1;
static_text1.id = 3;
static_text1.role = ax::mojom::Role::kStaticText;
static_text1.SetName(" *");
AXNodeData inline_text1;
inline_text1.id = 4;
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("*");
static_text1.child_ids = {inline_text1.id};
root.child_ids = {static_text1.id};
SetTree(CreateAXTree({root, static_text1, inline_text1}));
TestPositionType text_position = CreateTextPosition(
static_text1, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(text_position->AtStartOfLine());
}
TEST_F(AXPositionTest, AtEndOfLineWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(inline_box1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfLine());
text_position = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfLine());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(inline_box2_, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfLine());
}
TEST_F(AXPositionTest, AtStartOfBlankLine) {
inline_box1_.RemoveIntAttribute(ax::mojom::IntAttribute::kNextOnLineId);
line_break_.RemoveIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId);
AXTreeUpdate update;
update.nodes = {inline_box1_, line_break_};
ASSERT_TRUE(GetTree()->Unserialize(update));
TestPositionType tree_position =
CreateTreePosition(text_field_, 1 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_TRUE(tree_position->AtStartOfLine());
TestPositionType text_position = CreateTextPosition(
line_break_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
}
TEST_F(AXPositionTest, AtEndOfBlankLine) {
inline_box1_.RemoveIntAttribute(ax::mojom::IntAttribute::kNextOnLineId);
line_break_.RemoveIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId);
AXTreeUpdate update;
update.nodes = {inline_box1_, line_break_};
ASSERT_TRUE(GetTree()->Unserialize(update));
TestPositionType tree_position =
CreateTreePosition(text_field_, 1 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_FALSE(tree_position->AtEndOfLine());
TestPositionType text_position = CreateTextPosition(
line_break_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfLine());
}
TEST_F(AXPositionTest, AtStartAndEndOfLineWhenAtEndOfTextSpan) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
root_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData static_text_data_1;
static_text_data_1.id = 2;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.SetName("Hello testing ");
AXNodeData inline_box_data_1;
inline_box_data_1.id = 3;
inline_box_data_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_1.SetName("hello");
AXNodeData inline_box_data_2;
inline_box_data_2.id = 4;
inline_box_data_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_1.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box_data_2.id);
inline_box_data_2.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box_data_1.id);
inline_box_data_2.SetName(" ");
AXNodeData inline_box_data_3;
inline_box_data_3.id = 5;
inline_box_data_3.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_3.SetName("testing");
AXNodeData inline_box_data_4;
inline_box_data_4.id = 6;
inline_box_data_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_3.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box_data_4.id);
inline_box_data_4.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box_data_3.id);
inline_box_data_4.SetName(" ");
AXNodeData static_text_data_2;
static_text_data_2.id = 7;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName("here.");
AXNodeData inline_box_data_5;
inline_box_data_5.id = 8;
inline_box_data_5.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_5.SetName("here.");
static_text_data_1.child_ids = {inline_box_data_1.id, inline_box_data_2.id,
inline_box_data_3.id, inline_box_data_4.id};
static_text_data_2.child_ids = {inline_box_data_5.id};
root_data.child_ids = {static_text_data_1.id, static_text_data_2.id};
SetTree(CreateAXTree({root_data, static_text_data_1, inline_box_data_1,
inline_box_data_2, inline_box_data_3, inline_box_data_4,
static_text_data_2, inline_box_data_5}));
TestPositionType tree_position =
CreateTreePosition(inline_box_data_2, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_TRUE(tree_position->AtStartOfLine());
EXPECT_FALSE(tree_position->AtEndOfLine());
tree_position = CreateTreePosition(inline_box_data_4, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_FALSE(tree_position->AtStartOfLine());
EXPECT_TRUE(tree_position->AtEndOfLine());
TestPositionType text_position =
CreateTextPosition(inline_box_data_2, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(inline_box_data_4, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfLine());
EXPECT_TRUE(text_position->AtEndOfLine());
}
TEST_F(AXPositionTest, AtStartAndEndOfLineInsideTextField) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
root_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData text_field_data_1;
text_field_data_1.id = 2;
text_field_data_1.role = ax::mojom::Role::kTextField;
text_field_data_1.AddState(ax::mojom::State::kEditable);
text_field_data_1.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
text_field_data_1.AddState(ax::mojom::State::kEditable);
text_field_data_1.SetValue(" Text field one ");
AXNodeData static_text_data_1;
static_text_data_1.id = 3;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.AddState(ax::mojom::State::kEditable);
static_text_data_1.SetName(" Text field one ");
AXNodeData inline_box_data_1;
inline_box_data_1.id = 4;
inline_box_data_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_1.AddState(ax::mojom::State::kEditable);
inline_box_data_1.SetName(" ");
AXNodeData inline_box_data_2;
inline_box_data_2.id = 5;
inline_box_data_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_2.AddState(ax::mojom::State::kEditable);
inline_box_data_1.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box_data_2.id);
inline_box_data_2.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box_data_1.id);
inline_box_data_2.SetName("Text field one");
AXNodeData inline_box_data_3;
inline_box_data_3.id = 6;
inline_box_data_3.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_3.AddState(ax::mojom::State::kEditable);
inline_box_data_2.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box_data_3.id);
inline_box_data_3.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box_data_2.id);
inline_box_data_3.SetName(" ");
AXNodeData text_field_data_2;
text_field_data_2.id = 7;
text_field_data_2.role = ax::mojom::Role::kTextField;
text_field_data_2.AddState(ax::mojom::State::kEditable);
text_field_data_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
text_field_data_2.SetValue(" Text field two ");
AXNodeData static_text_data_2;
static_text_data_2.id = 8;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.AddState(ax::mojom::State::kEditable);
static_text_data_2.SetName(" Text field two ");
AXNodeData inline_box_data_4;
inline_box_data_4.id = 9;
inline_box_data_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_4.AddState(ax::mojom::State::kEditable);
inline_box_data_4.SetName(" ");
AXNodeData inline_box_data_5;
inline_box_data_5.id = 10;
inline_box_data_5.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_5.AddState(ax::mojom::State::kEditable);
inline_box_data_5.SetName("Text field two");
AXNodeData inline_box_data_6;
inline_box_data_6.id = 11;
inline_box_data_6.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_6.AddState(ax::mojom::State::kEditable);
inline_box_data_6.SetName(" ");
static_text_data_1.child_ids = {inline_box_data_1.id, inline_box_data_2.id,
inline_box_data_3.id};
static_text_data_2.child_ids = {inline_box_data_4.id, inline_box_data_5.id,
inline_box_data_6.id};
text_field_data_1.child_ids = {static_text_data_1.id};
text_field_data_2.child_ids = {static_text_data_2.id};
root_data.child_ids = {text_field_data_1.id, text_field_data_2.id};
SetTree(
CreateAXTree({root_data, text_field_data_1, static_text_data_1,
inline_box_data_1, inline_box_data_2, inline_box_data_3,
text_field_data_2, static_text_data_2, inline_box_data_4,
inline_box_data_5, inline_box_data_6}));
TestPositionType tree_position =
CreateTreePosition(text_field_data_1, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_TRUE(tree_position->AtStartOfLine());
EXPECT_FALSE(tree_position->AtEndOfLine());
tree_position = CreateTreePosition(text_field_data_1, 1 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_FALSE(tree_position->AtStartOfLine());
EXPECT_TRUE(tree_position->AtEndOfLine());
tree_position = CreateTreePosition(text_field_data_2, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_TRUE(tree_position->AtStartOfLine());
EXPECT_FALSE(tree_position->AtEndOfLine());
tree_position = CreateTreePosition(text_field_data_2, 1 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_FALSE(tree_position->AtStartOfLine());
EXPECT_TRUE(tree_position->AtEndOfLine());
TestPositionType text_position =
CreateTextPosition(text_field_data_1, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(text_field_data_1, 16 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfLine());
EXPECT_TRUE(text_position->AtEndOfLine());
text_position = CreateTextPosition(text_field_data_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfLine());
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = CreateTextPosition(text_field_data_2, 16 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfLine());
EXPECT_TRUE(text_position->AtEndOfLine());
}
TEST_F(AXPositionTest, AtStartOfParagraphWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(inline_box1_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(inline_box2_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtStartOfParagraph());
}
TEST_F(AXPositionTest, AtEndOfParagraphWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box2_, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->AtEndOfParagraph());
}
TEST_F(AXPositionTest, AtStartOrEndOfParagraphWithPreservedNewLine) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
root_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData static_text_data_1;
static_text_data_1.id = 2;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.SetName("some text");
AXNodeData some_text_data;
some_text_data.id = 3;
some_text_data.role = ax::mojom::Role::kInlineTextBox;
some_text_data.SetName("some text");
AXNodeData container_data;
container_data.id = 4;
container_data.role = ax::mojom::Role::kGenericContainer;
container_data.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_2;
static_text_data_2.id = 5;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName("\nmore text");
AXNodeData preserved_newline_data;
preserved_newline_data.id = 6;
preserved_newline_data.role = ax::mojom::Role::kInlineTextBox;
preserved_newline_data.SetName("\n");
preserved_newline_data.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData more_text_data;
more_text_data.id = 7;
more_text_data.role = ax::mojom::Role::kInlineTextBox;
more_text_data.SetName("more text");
static_text_data_1.child_ids = {some_text_data.id};
container_data.child_ids = {static_text_data_2.id};
static_text_data_2.child_ids = {preserved_newline_data.id, more_text_data.id};
root_data.child_ids = {static_text_data_1.id, container_data.id};
SetTree(CreateAXTree({root_data, static_text_data_1, some_text_data,
container_data, static_text_data_2,
preserved_newline_data, more_text_data}));
TestPositionType text_position1 = CreateTextPosition(
root_data, 8 , ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position1->AtEndOfParagraph());
EXPECT_FALSE(text_position1->AtStartOfParagraph());
TestPositionType text_position2 = CreateTextPosition(
root_data, 9 , ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position2->AtEndOfParagraph());
EXPECT_TRUE(text_position2->AtStartOfParagraph());
TestPositionType text_position3 = CreateTextPosition(
root_data, 9 , ax::mojom::TextAffinity::kUpstream);
EXPECT_TRUE(text_position3->AtEndOfParagraph());
EXPECT_FALSE(text_position3->AtStartOfParagraph());
TestPositionType text_position4 = CreateTextPosition(
root_data, 10 , ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position4->AtEndOfParagraph());
EXPECT_TRUE(text_position4->AtStartOfParagraph());
TestPositionType text_position5 = CreateTextPosition(
root_data, 10 , ax::mojom::TextAffinity::kUpstream);
EXPECT_FALSE(text_position5->AtEndOfParagraph());
EXPECT_FALSE(text_position5->AtStartOfParagraph());
TestPositionType text_position6 =
CreateTextPosition(container_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position6->AtEndOfParagraph());
EXPECT_TRUE(text_position6->AtStartOfParagraph());
TestPositionType text_position7 =
CreateTextPosition(container_data, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position7->AtEndOfParagraph());
EXPECT_TRUE(text_position7->AtStartOfParagraph());
TestPositionType text_position8 = CreateTextPosition(
container_data, 1 , ax::mojom::TextAffinity::kUpstream);
EXPECT_FALSE(text_position8->AtEndOfParagraph());
EXPECT_FALSE(text_position8->AtStartOfParagraph());
TestPositionType text_position9 =
CreateTextPosition(static_text_data_2, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position9->AtEndOfParagraph());
EXPECT_TRUE(text_position9->AtStartOfParagraph());
TestPositionType text_position10 =
CreateTextPosition(static_text_data_2, 1 ,
ax::mojom::TextAffinity::kUpstream);
EXPECT_FALSE(text_position10->AtEndOfParagraph());
EXPECT_FALSE(text_position10->AtStartOfParagraph());
TestPositionType text_position11 =
CreateTextPosition(preserved_newline_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position11->AtEndOfParagraph());
EXPECT_TRUE(text_position11->AtStartOfParagraph());
TestPositionType text_position12 =
CreateTextPosition(preserved_newline_data, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position12->AtEndOfParagraph());
EXPECT_FALSE(text_position12->AtStartOfParagraph());
TestPositionType text_position13 =
CreateTextPosition(more_text_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position13->AtEndOfParagraph());
EXPECT_TRUE(text_position13->AtStartOfParagraph());
TestPositionType text_position14 =
CreateTextPosition(more_text_data, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position14->AtEndOfParagraph());
EXPECT_FALSE(text_position14->AtStartOfParagraph());
}
TEST_F(AXPositionTest, TreePositionAtStartOrEndOfListMarkerAnchor) {
AXNodeData root;
AXNodeData list;
AXNodeData list_item;
AXNodeData list_marker;
AXNodeData static_text;
root.id = 1;
list.id = 2;
list_item.id = 3;
list_marker.id = 4;
static_text.id = 5;
root.role = ax::mojom::Role::kRootWebArea;
root.child_ids = {list.id};
list.role = ax::mojom::Role::kList;
list.child_ids = {list_item.id};
list_item.role = ax::mojom::Role::kListItem;
list_item.child_ids = {list_marker.id};
list_marker.role = ax::mojom::Role::kListMarker;
list_marker.SetName("1. ");
list_marker.SetNameFrom(ax::mojom::NameFrom::kContents);
list_marker.child_ids = {static_text.id};
static_text.role = ax::mojom::Role::kStaticText;
static_text.SetName("1. ");
static_text.AddState(ax::mojom::State::kIgnored);
SetTree(CreateAXTree({root, list, list_item, list_marker, static_text}));
TestPositionType tree_position = CreateTreePosition(list_marker, 1);
ASSERT_NE(nullptr, tree_position);
EXPECT_EQ(AXPositionKind::TREE_POSITION, tree_position->kind());
EXPECT_TRUE(tree_position->IsLeaf());
EXPECT_FALSE(tree_position->IsIgnored());
TestPositionType start_of_anchor =
tree_position->CreatePositionAtStartOfAnchor();
EXPECT_NE(nullptr, start_of_anchor);
EXPECT_EQ(AXPositionKind::TREE_POSITION, start_of_anchor->kind());
EXPECT_TRUE(start_of_anchor->IsLeaf());
EXPECT_FALSE(start_of_anchor->IsIgnored());
TestPositionType end_of_anchor = tree_position->CreatePositionAtEndOfAnchor();
EXPECT_NE(nullptr, end_of_anchor);
EXPECT_EQ(AXPositionKind::TREE_POSITION, end_of_anchor->kind());
EXPECT_TRUE(end_of_anchor->IsLeaf());
EXPECT_FALSE(end_of_anchor->IsIgnored());
}
TEST_F(AXPositionTest, AtStartOrEndOfParagraphOnAListMarker) {
AXNodeData root;
AXNodeData list;
AXNodeData list_item1;
AXNodeData list_item2;
AXNodeData list_marker_legacy;
AXNodeData list_marker_ng;
AXNodeData static_text1;
AXNodeData static_text2;
AXNodeData static_text3;
AXNodeData static_text4;
AXNodeData static_text5;
AXNodeData inline_box1;
AXNodeData inline_box3;
AXNodeData inline_box4;
AXNodeData inline_box5;
root.id = 1;
static_text1.id = 2;
inline_box1.id = 3;
list.id = 4;
list_item1.id = 5;
list_marker_legacy.id = 6;
static_text2.id = 7;
static_text3.id = 9;
inline_box3.id = 10;
list_item2.id = 11;
list_marker_ng.id = 12;
static_text4.id = 13;
inline_box4.id = 14;
static_text5.id = 15;
inline_box5.id = 16;
root.role = ax::mojom::Role::kRootWebArea;
root.child_ids = {static_text1.id, list.id, static_text5.id};
root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text1.role = ax::mojom::Role::kStaticText;
static_text1.child_ids = {inline_box1.id};
static_text1.SetName("Before list.");
inline_box1.role = ax::mojom::Role::kInlineTextBox;
inline_box1.SetName("Before list.");
list.role = ax::mojom::Role::kList;
list.child_ids = {list_item1.id, list_item2.id};
list_item1.role = ax::mojom::Role::kListItem;
list_item1.child_ids = {list_marker_legacy.id, static_text3.id};
list_item1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
list_marker_legacy.role = ax::mojom::Role::kListMarker;
list_marker_legacy.SetName("1. ");
list_marker_legacy.SetNameFrom(ax::mojom::NameFrom::kContents);
list_marker_legacy.child_ids = {static_text2.id};
static_text2.role = ax::mojom::Role::kStaticText;
static_text2.SetName("1. ");
static_text2.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box3.id);
static_text2.AddState(ax::mojom::State::kIgnored);
static_text3.role = ax::mojom::Role::kStaticText;
static_text3.child_ids = {inline_box3.id};
static_text3.SetName("First item.");
inline_box3.role = ax::mojom::Role::kInlineTextBox;
inline_box3.SetName("First item.");
inline_box3.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
static_text2.id);
list_item2.role = ax::mojom::Role::kListItem;
list_item2.child_ids = {list_marker_ng.id, static_text4.id};
list_item2.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
list_marker_ng.role = ax::mojom::Role::kListMarker;
list_marker_ng.SetName("2. ");
list_marker_ng.SetNameFrom(ax::mojom::NameFrom::kContents);
list_marker_ng.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box4.id);
static_text4.role = ax::mojom::Role::kStaticText;
static_text4.child_ids = {inline_box4.id};
static_text4.SetName("Second item.");
inline_box4.role = ax::mojom::Role::kInlineTextBox;
inline_box4.SetName("Second item.");
inline_box4.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
list_marker_ng.id);
static_text5.role = ax::mojom::Role::kStaticText;
static_text5.child_ids = {inline_box5.id};
static_text5.SetName("After list.");
inline_box5.role = ax::mojom::Role::kInlineTextBox;
inline_box5.SetName("After list.");
SetTree(CreateAXTree({root, static_text1, inline_box1, list, list_item1,
list_marker_legacy, static_text2, static_text3,
inline_box3, list_item2, list_marker_ng, static_text4,
inline_box4, static_text5, inline_box5}));
TestPositionType text_position = CreateTextPosition(
static_text1, 12 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box1, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list, 14 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list, 14 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list_marker_legacy, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeaf());
EXPECT_FALSE(text_position->IsIgnored());
EXPECT_TRUE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list_marker_legacy, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeaf());
EXPECT_FALSE(text_position->IsIgnored());
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list_marker_legacy, 2 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeaf());
EXPECT_FALSE(text_position->IsIgnored());
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list_marker_legacy, 3 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeaf());
EXPECT_FALSE(text_position->IsIgnored());
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list_marker_ng, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeaf());
EXPECT_TRUE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(list_marker_ng, 3 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeaf());
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(static_text3, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box3, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(static_text3, 11 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box3, 11 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(static_text4, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box4, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(static_text4, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box4, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtStartOfParagraph());
EXPECT_TRUE(text_position->AtEndOfParagraph());
text_position = CreateTextPosition(inline_box5, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->AtStartOfParagraph());
EXPECT_FALSE(text_position->AtEndOfParagraph());
}
TEST_F(AXPositionTest,
AtStartOrEndOfParagraphWithLeadingAndTrailingWhitespace) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
root_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData container_data_a;
container_data_a.id = 2;
container_data_a.role = ax::mojom::Role::kGenericContainer;
container_data_a.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_a;
static_text_data_a.id = 3;
static_text_data_a.role = ax::mojom::Role::kStaticText;
static_text_data_a.SetName("\n");
AXNodeData inline_text_data_a;
inline_text_data_a.id = 4;
inline_text_data_a.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_a.SetName("\n");
inline_text_data_a.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData container_data_b;
container_data_b.id = 5;
container_data_b.role = ax::mojom::Role::kGenericContainer;
container_data_b.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_b;
static_text_data_b.id = 6;
static_text_data_b.role = ax::mojom::Role::kStaticText;
static_text_data_b.SetName("some text");
AXNodeData inline_text_data_b_1;
inline_text_data_b_1.id = 7;
inline_text_data_b_1.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_1.SetName("some");
AXNodeData inline_text_data_b_2;
inline_text_data_b_2.id = 8;
inline_text_data_b_2.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_2.SetName(" ");
AXNodeData inline_text_data_b_3;
inline_text_data_b_3.id = 9;
inline_text_data_b_3.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_3.SetName("text");
AXNodeData container_data_c;
container_data_c.id = 10;
container_data_c.role = ax::mojom::Role::kGenericContainer;
container_data_c.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_c;
static_text_data_c.id = 11;
static_text_data_c.role = ax::mojom::Role::kStaticText;
static_text_data_c.SetName("\n");
AXNodeData inline_text_data_c;
inline_text_data_c.id = 12;
inline_text_data_c.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_c.SetName("\n");
inline_text_data_c.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
root_data.child_ids = {container_data_a.id, container_data_b.id,
container_data_c.id};
container_data_a.child_ids = {static_text_data_a.id};
static_text_data_a.child_ids = {inline_text_data_a.id};
container_data_b.child_ids = {static_text_data_b.id};
static_text_data_b.child_ids = {inline_text_data_b_1.id,
inline_text_data_b_2.id,
inline_text_data_b_3.id};
container_data_c.child_ids = {static_text_data_c.id};
static_text_data_c.child_ids = {inline_text_data_c.id};
SetTree(CreateAXTree(
{root_data, container_data_a, container_data_b, container_data_c,
static_text_data_a, static_text_data_b, static_text_data_c,
inline_text_data_a, inline_text_data_b_1, inline_text_data_b_2,
inline_text_data_b_3, inline_text_data_c}));
TestPositionType text_position1 =
CreateTextPosition(inline_text_data_a, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position1->AtEndOfParagraph());
EXPECT_TRUE(text_position1->AtStartOfParagraph());
TestPositionType text_position2 =
CreateTextPosition(inline_text_data_a, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position2->AtEndOfParagraph());
EXPECT_FALSE(text_position2->AtStartOfParagraph());
TestPositionType text_position3 =
CreateTextPosition(inline_text_data_b_1, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position3->AtEndOfParagraph());
EXPECT_TRUE(text_position3->AtStartOfParagraph());
TestPositionType text_position4 =
CreateTextPosition(inline_text_data_b_1, 4 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position4->AtEndOfParagraph());
EXPECT_FALSE(text_position4->AtStartOfParagraph());
TestPositionType text_position5 =
CreateTextPosition(inline_text_data_b_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position5->AtEndOfParagraph());
EXPECT_FALSE(text_position5->AtStartOfParagraph());
TestPositionType text_position6 =
CreateTextPosition(inline_text_data_b_2, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position6->AtEndOfParagraph());
EXPECT_FALSE(text_position6->AtStartOfParagraph());
TestPositionType text_position7 =
CreateTextPosition(inline_text_data_b_3, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position7->AtEndOfParagraph());
EXPECT_FALSE(text_position7->AtStartOfParagraph());
TestPositionType text_position8 =
CreateTextPosition(inline_text_data_b_3, 4 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position8->AtEndOfParagraph());
EXPECT_FALSE(text_position8->AtStartOfParagraph());
TestPositionType text_position9 =
CreateTextPosition(inline_text_data_c, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position9->AtEndOfParagraph());
EXPECT_TRUE(text_position9->AtStartOfParagraph());
TestPositionType text_position10 =
CreateTextPosition(inline_text_data_c, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position10->AtEndOfParagraph());
EXPECT_FALSE(text_position10->AtStartOfParagraph());
}
TEST_F(AXPositionTest, AtStartOrEndOfParagraphWithIgnoredNodes) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
root_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData container_data_a;
container_data_a.id = 2;
container_data_a.role = ax::mojom::Role::kGenericContainer;
container_data_a.AddState(ax::mojom::State::kIgnored);
container_data_a.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_a;
static_text_data_a.id = 3;
static_text_data_a.role = ax::mojom::Role::kStaticText;
static_text_data_a.SetName("ignored text");
static_text_data_a.AddState(ax::mojom::State::kIgnored);
AXNodeData inline_text_data_a;
inline_text_data_a.id = 4;
inline_text_data_a.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_a.SetName("ignored text");
inline_text_data_a.AddState(ax::mojom::State::kIgnored);
AXNodeData container_data_b;
container_data_b.id = 5;
container_data_b.role = ax::mojom::Role::kGenericContainer;
container_data_b.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_b;
static_text_data_b.id = 6;
static_text_data_b.role = ax::mojom::Role::kStaticText;
static_text_data_b.SetName("some text");
AXNodeData inline_text_data_b_1;
inline_text_data_b_1.id = 7;
inline_text_data_b_1.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_1.SetName("some");
AXNodeData inline_text_data_b_2;
inline_text_data_b_2.id = 8;
inline_text_data_b_2.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_2.SetName(" ");
AXNodeData inline_text_data_b_3;
inline_text_data_b_3.id = 9;
inline_text_data_b_3.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_3.SetName("text");
AXNodeData container_data_c;
container_data_c.id = 10;
container_data_c.role = ax::mojom::Role::kGenericContainer;
container_data_c.AddState(ax::mojom::State::kIgnored);
container_data_c.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_c;
static_text_data_c.id = 11;
static_text_data_c.role = ax::mojom::Role::kStaticText;
static_text_data_c.SetName("ignored text");
static_text_data_c.AddState(ax::mojom::State::kIgnored);
AXNodeData inline_text_data_c;
inline_text_data_c.id = 12;
inline_text_data_c.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_c.SetName("ignored text");
inline_text_data_c.AddState(ax::mojom::State::kIgnored);
root_data.child_ids = {container_data_a.id, container_data_b.id,
container_data_c.id};
container_data_a.child_ids = {static_text_data_a.id};
static_text_data_a.child_ids = {inline_text_data_a.id};
container_data_b.child_ids = {static_text_data_b.id};
static_text_data_b.child_ids = {inline_text_data_b_1.id,
inline_text_data_b_2.id,
inline_text_data_b_3.id};
container_data_c.child_ids = {static_text_data_c.id};
static_text_data_c.child_ids = {inline_text_data_c.id};
SetTree(CreateAXTree(
{root_data, container_data_a, container_data_b, container_data_c,
static_text_data_a, static_text_data_b, static_text_data_c,
inline_text_data_a, inline_text_data_b_1, inline_text_data_b_2,
inline_text_data_b_3, inline_text_data_c}));
TestPositionType text_position1 =
CreateTextPosition(inline_text_data_a, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position1->AtEndOfParagraph());
EXPECT_TRUE(text_position1->AtStartOfParagraph());
TestPositionType text_position2 =
CreateTextPosition(inline_text_data_a, 12 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position2->AtEndOfParagraph());
EXPECT_FALSE(text_position2->AtStartOfParagraph());
TestPositionType text_position3 =
CreateTextPosition(inline_text_data_b_1, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position3->AtEndOfParagraph());
EXPECT_TRUE(text_position3->AtStartOfParagraph());
TestPositionType text_position4 =
CreateTextPosition(inline_text_data_b_1, 4 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position4->AtEndOfParagraph());
EXPECT_FALSE(text_position4->AtStartOfParagraph());
TestPositionType text_position5 =
CreateTextPosition(inline_text_data_b_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position5->AtEndOfParagraph());
EXPECT_FALSE(text_position5->AtStartOfParagraph());
TestPositionType text_position6 =
CreateTextPosition(inline_text_data_b_2, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position6->AtEndOfParagraph());
EXPECT_FALSE(text_position6->AtStartOfParagraph());
TestPositionType text_position7 =
CreateTextPosition(inline_text_data_b_3, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position7->AtEndOfParagraph());
EXPECT_FALSE(text_position7->AtStartOfParagraph());
TestPositionType text_position8 =
CreateTextPosition(inline_text_data_b_3, 4 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position8->AtEndOfParagraph());
EXPECT_FALSE(text_position8->AtStartOfParagraph());
TestPositionType text_position9 =
CreateTextPosition(inline_text_data_c, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position9->AtEndOfParagraph());
EXPECT_TRUE(text_position9->AtStartOfParagraph());
TestPositionType text_position10 =
CreateTextPosition(inline_text_data_c, 12 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position10->AtEndOfParagraph());
EXPECT_FALSE(text_position10->AtStartOfParagraph());
}
TEST_F(AXPositionTest, AtStartOrEndOfParagraphWithEmbeddedObjectCharacter) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData link_2;
AXNodeData static_text_3;
AXNodeData inline_box_4;
AXNodeData image_5;
AXNodeData static_text_6;
AXNodeData inline_box_7;
root_1.id = 1;
link_2.id = 2;
static_text_3.id = 3;
inline_box_4.id = 4;
image_5.id = 5;
static_text_6.id = 6;
inline_box_7.id = 7;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {link_2.id};
root_1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
link_2.role = ax::mojom::Role::kLink;
link_2.child_ids = {static_text_3.id, image_5.id, static_text_6.id};
static_text_3.role = ax::mojom::Role::kStaticText;
static_text_3.child_ids = {inline_box_4.id};
static_text_3.SetName("Hello");
inline_box_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_4.SetName("Hello");
image_5.role = ax::mojom::Role::kImage;
static_text_6.role = ax::mojom::Role::kStaticText;
static_text_6.child_ids = {inline_box_7.id};
static_text_6.SetName("world");
inline_box_7.role = ax::mojom::Role::kInlineTextBox;
inline_box_7.SetName("world");
SetTree(CreateAXTree({root_1, link_2, static_text_3, inline_box_4, image_5,
static_text_6, inline_box_7}));
TestPositionType text_position = CreateTextPosition(
inline_box_4, 0 , ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position->AtEndOfParagraph());
EXPECT_TRUE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(inline_box_4, 5 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->AtEndOfParagraph());
EXPECT_FALSE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(image_5, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position->AtEndOfParagraph());
EXPECT_TRUE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(image_5, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->AtEndOfParagraph());
EXPECT_FALSE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(inline_box_7, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(text_position->AtEndOfParagraph());
EXPECT_TRUE(text_position->AtStartOfParagraph());
text_position = CreateTextPosition(inline_box_7, 5 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->AtEndOfParagraph());
EXPECT_FALSE(text_position->AtStartOfParagraph());
}
TEST_F(AXPositionTest, CreateNextOrPreviousParagraphPositionWithIgnoredNodes) {
AXNodeData root_data;
root_data.id = 1;
AXNodeData static_text_data_a;
static_text_data_a.id = 2;
AXNodeData inline_text_data_a;
inline_text_data_a.id = 3;
AXNodeData ignored_container_data_a;
ignored_container_data_a.id = 4;
AXNodeData static_text_data_b;
static_text_data_b.id = 5;
AXNodeData inline_text_data_b_1;
inline_text_data_b_1.id = 6;
AXNodeData inline_text_data_b_2;
inline_text_data_b_2.id = 7;
AXNodeData inline_text_data_b_3;
inline_text_data_b_3.id = 8;
AXNodeData ignored_container_data_b;
ignored_container_data_b.id = 9;
AXNodeData static_text_data_c;
static_text_data_c.id = 10;
AXNodeData inline_text_data_c;
inline_text_data_c.id = 11;
root_data.role = ax::mojom::Role::kRootWebArea;
root_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
root_data.child_ids = {static_text_data_a.id, ignored_container_data_a.id,
static_text_data_b.id, ignored_container_data_b.id,
static_text_data_c.id};
static_text_data_a.role = ax::mojom::Role::kStaticText;
static_text_data_a.SetName("First paragraph");
static_text_data_a.child_ids = {inline_text_data_a.id};
inline_text_data_a.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_a.SetName("First paragraph");
ignored_container_data_a.role = ax::mojom::Role::kGenericContainer;
ignored_container_data_a.AddState(ax::mojom::State::kIgnored);
ignored_container_data_a.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_data_b.role = ax::mojom::Role::kStaticText;
static_text_data_b.SetName("Second paragraph");
static_text_data_b.child_ids = {inline_text_data_b_1.id,
inline_text_data_b_2.id,
inline_text_data_b_3.id};
inline_text_data_b_1.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_1.SetName("Paragraph");
inline_text_data_b_2.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_2.SetName(" ");
inline_text_data_b_3.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_b_3.SetName("paragraph");
ignored_container_data_b.role = ax::mojom::Role::kGenericContainer;
ignored_container_data_b.AddState(ax::mojom::State::kIgnored);
ignored_container_data_b.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_data_c.role = ax::mojom::Role::kStaticText;
static_text_data_c.SetName("Third paragraph");
static_text_data_c.child_ids = {inline_text_data_c.id};
inline_text_data_c.role = ax::mojom::Role::kInlineTextBox;
inline_text_data_c.SetName("Third paragraph");
SetTree(CreateAXTree({root_data, static_text_data_a, inline_text_data_a,
ignored_container_data_a, static_text_data_b,
inline_text_data_b_1, inline_text_data_b_2,
inline_text_data_b_3, ignored_container_data_b,
static_text_data_c, inline_text_data_c}));
TestPositionType paragraph_start_position =
CreateTextPosition(inline_text_data_a, 0 ,
ax::mojom::TextAffinity::kDownstream);
paragraph_start_position =
paragraph_start_position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_start_position->IsTextPosition());
EXPECT_EQ(inline_text_data_b_1.id, paragraph_start_position->anchor_id());
EXPECT_EQ(0, paragraph_start_position->text_offset());
paragraph_start_position =
paragraph_start_position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_start_position->IsTextPosition());
EXPECT_EQ(inline_text_data_c.id, paragraph_start_position->anchor_id());
EXPECT_EQ(0, paragraph_start_position->text_offset());
paragraph_start_position =
paragraph_start_position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(paragraph_start_position->IsNullPosition());
paragraph_start_position =
CreateTextPosition(inline_text_data_c, 15 ,
ax::mojom::TextAffinity::kDownstream);
paragraph_start_position =
paragraph_start_position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_start_position->IsTextPosition());
EXPECT_EQ(inline_text_data_c.id, paragraph_start_position->anchor_id());
EXPECT_EQ(0, paragraph_start_position->text_offset());
paragraph_start_position =
paragraph_start_position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_start_position->IsTextPosition());
EXPECT_EQ(inline_text_data_b_1.id, paragraph_start_position->anchor_id());
EXPECT_EQ(0, paragraph_start_position->text_offset());
paragraph_start_position =
paragraph_start_position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_start_position->IsTextPosition());
EXPECT_EQ(inline_text_data_a.id, paragraph_start_position->anchor_id());
EXPECT_EQ(0, paragraph_start_position->text_offset());
paragraph_start_position =
paragraph_start_position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(paragraph_start_position->IsNullPosition());
TestPositionType paragraph_end_position =
CreateTextPosition(inline_text_data_a, 0 ,
ax::mojom::TextAffinity::kDownstream);
paragraph_end_position =
paragraph_end_position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_end_position->IsTextPosition());
EXPECT_EQ(inline_text_data_a.id, paragraph_end_position->anchor_id());
EXPECT_EQ(15, paragraph_end_position->text_offset());
paragraph_end_position =
paragraph_end_position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_end_position->IsTextPosition());
EXPECT_EQ(inline_text_data_b_3.id, paragraph_end_position->anchor_id());
EXPECT_EQ(9, paragraph_end_position->text_offset());
paragraph_end_position =
paragraph_end_position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_end_position->IsTextPosition());
EXPECT_EQ(inline_text_data_c.id, paragraph_end_position->anchor_id());
EXPECT_EQ(15, paragraph_end_position->text_offset());
paragraph_end_position =
paragraph_end_position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(paragraph_end_position->IsNullPosition());
paragraph_end_position =
CreateTextPosition(inline_text_data_c, 15 ,
ax::mojom::TextAffinity::kDownstream);
paragraph_end_position =
paragraph_end_position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_end_position->IsTextPosition());
EXPECT_EQ(inline_text_data_b_3.id, paragraph_end_position->anchor_id());
EXPECT_EQ(9, paragraph_end_position->text_offset());
paragraph_end_position =
paragraph_end_position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_TRUE(paragraph_end_position->IsTextPosition());
EXPECT_EQ(inline_text_data_a.id, paragraph_end_position->anchor_id());
EXPECT_EQ(15, paragraph_end_position->text_offset());
paragraph_end_position =
paragraph_end_position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(paragraph_end_position->IsNullPosition());
}
TEST_F(
AXPositionTest,
CreatePreviousParagraphEndPositionStopAtAnchorBoundaryWithConsecutiveParentChildLineBreakingObjects) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData static_text_data_a;
static_text_data_a.id = 2;
static_text_data_a.role = ax::mojom::Role::kStaticText;
static_text_data_a.SetName("first");
AXNodeData container_data_a;
container_data_a.id = 3;
container_data_a.role = ax::mojom::Role::kGenericContainer;
container_data_a.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData container_data_b;
container_data_b.id = 4;
container_data_b.role = ax::mojom::Role::kGenericContainer;
container_data_b.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData static_text_data_b;
static_text_data_b.id = 5;
static_text_data_b.role = ax::mojom::Role::kStaticText;
static_text_data_b.SetName("second");
root_data.child_ids = {static_text_data_a.id, container_data_a.id};
container_data_a.child_ids = {container_data_b.id, static_text_data_b.id};
SetTree(CreateAXTree({root_data, static_text_data_a, container_data_a,
container_data_b, static_text_data_b}));
TestPositionType test_position = CreateTextPosition(
root_data, 11 , ax::mojom::TextAffinity::kDownstream);
test_position = test_position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(root_data.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
}
TEST_F(AXPositionTest, LowestCommonAncestor) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType root_position =
CreateTreePosition(root_, 3 );
ASSERT_NE(nullptr, root_position);
TestPositionType button_position =
CreateTreePosition(button_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, button_position);
TestPositionType text_field_position =
CreateTreePosition(text_field_, 2 );
ASSERT_NE(nullptr, text_field_position);
TestPositionType static_text1_position =
CreateTreePosition(static_text1_, 0 );
ASSERT_NE(nullptr, static_text1_position);
TestPositionType static_text2_position =
CreateTreePosition(static_text2_, 0 );
ASSERT_NE(nullptr, static_text2_position);
TestPositionType inline_box1_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, inline_box1_position);
ASSERT_TRUE(inline_box1_position->IsTextPosition());
TestPositionType inline_box2_position = CreateTextPosition(
inline_box2_, 0 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, inline_box2_position);
ASSERT_TRUE(inline_box2_position->IsTextPosition());
TestPositionType test_position = root_position->LowestCommonAncestorPosition(
*null_position.get(), ax::mojom::MoveDirection::kForward);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = root_position->LowestCommonAncestorPosition(
*root_position.get(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->child_index());
test_position = button_position->LowestCommonAncestorPosition(
*text_field_position.get(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = static_text2_position->LowestCommonAncestorPosition(
*static_text1_position.get(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(2, test_position->child_index());
test_position = static_text1_position->LowestCommonAncestorPosition(
*text_field_position.get(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = inline_box1_position->LowestCommonAncestorPosition(
*inline_box2_position.get(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = inline_box2_position->LowestCommonAncestorPosition(
*inline_box1_position.get(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(7, test_position->text_offset());
}
TEST_F(AXPositionTest, AsTreePositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->AsTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsTreePositionWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->AsTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->child_index());
EXPECT_EQ(AXNodePosition::INVALID_OFFSET, test_position->text_offset());
}
TEST_F(AXPositionTest, AsTreePositionWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
text_field_, 12 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->AsTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(2, test_position->child_index());
EXPECT_EQ(12, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
EXPECT_EQ(6, test_position->text_offset());
}
TEST_F(AXPositionTest, AsTextPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->AsTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsTextPositionWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(text_field_, 1 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->AsTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(1, test_position->child_index());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position = CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->AsTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position = CreateTreePosition(inline_box1_, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->AsTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(0, test_position->child_index());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, AsTextPositionWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
text_field_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->AsTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
EXPECT_EQ(AXNodePosition::INVALID_INDEX, test_position->child_index());
}
TEST_F(AXPositionTest, AsLeafTreePositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsLeafTreePositionWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(text_field_, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position = CreateTreePosition(text_field_, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position = CreateTreePosition(text_field_, 2 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
}
TEST_F(AXPositionTest, AsLeafTreePositionWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
root_, 13 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
text_position = CreateTextPosition(root_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
text_position = CreateTextPosition(root_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
text_position = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
text_position = CreateTextPosition(root_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
text_position = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
text_position = CreateTextPosition(text_field_, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
text_position = CreateTextPosition(root_, 10 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTreePosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTreePosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
}
TEST_F(AXPositionTest, AsLeafTextPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsLeafTextPositionWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(text_field_, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position = CreateTreePosition(text_field_, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position = CreateTreePosition(text_field_, 2 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest,
AsLeafTextPositionWithTreePositionAndEmptyLeafDescendants) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData empty_div_data1;
empty_div_data1.id = 2;
empty_div_data1.role = ax::mojom::Role::kGenericContainer;
AXNodeData empty_div_data2;
empty_div_data2.id = 3;
empty_div_data2.role = ax::mojom::Role::kGenericContainer;
root_data.child_ids = {empty_div_data1.id, empty_div_data2.id};
SetTree(CreateAXTree({root_data, empty_div_data1, empty_div_data2}));
TestPositionType tree_position =
CreateTreePosition(root_data, 1 );
ASSERT_FALSE(tree_position->IsLeafTextPosition());
TestPositionType test_position = tree_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(empty_div_data2.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position = CreateTreePosition(root_data, 2 );
ASSERT_FALSE(tree_position->IsLeafTextPosition());
test_position = tree_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(empty_div_data2.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, AsLeafTextPositionWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
root_, 13 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_FALSE(text_position->IsLeafTextPosition());
TestPositionType test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_, 10 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_, 10 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, AsLeafTextPositionWithTextPositionAndEmptyTextSandwich) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_data;
text_data.id = 2;
text_data.role = ax::mojom::Role::kInlineTextBox;
text_data.SetName("some text");
AXNodeData button_data;
button_data.id = 3;
button_data.role = ax::mojom::Role::kButton;
button_data.SetNameExplicitlyEmpty();
button_data.SetNameFrom(ax::mojom::NameFrom::kContents);
AXNodeData more_text_data;
more_text_data.id = 4;
more_text_data.role = ax::mojom::Role::kInlineTextBox;
more_text_data.SetName("more text");
root_data.child_ids = {text_data.id, button_data.id, more_text_data.id};
SetTree(CreateAXTree({root_data, text_data, button_data, more_text_data}));
TestPositionType text_position = CreateTextPosition(
root_data, 9 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_FALSE(text_position->IsLeafTextPosition());
TestPositionType test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(button_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_data, 9 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->AsLeafTextPosition();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsLeafTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(text_data.id, test_position->anchor_id());
EXPECT_EQ(9, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, AsLeafTextPositionWithTextPositionAndEmbeddedObject) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root;
AXNodeData image;
AXNodeData paragraph;
AXNodeData link;
AXNodeData static_text;
AXNodeData inline_box;
root.id = 1;
image.id = 2;
paragraph.id = 3;
link.id = 4;
static_text.id = 5;
inline_box.id = 6;
root.role = ax::mojom::Role::kRootWebArea;
root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
root.child_ids = {image.id, paragraph.id};
image.role = ax::mojom::Role::kImage;
image.SetName("Test image");
image.SetNameFrom(ax::mojom::NameFrom::kAttribute);
paragraph.role = ax::mojom::Role::kParagraph;
paragraph.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph.child_ids = {link.id};
link.role = ax::mojom::Role::kLink;
link.AddState(ax::mojom::State::kLinked);
link.child_ids = {static_text.id};
static_text.role = ax::mojom::Role::kStaticText;
static_text.SetName("Hello");
static_text.child_ids = {inline_box.id};
inline_box.role = ax::mojom::Role::kInlineTextBox;
inline_box.SetName("Hello");
SetTree(
CreateAXTree({root, image, paragraph, link, static_text, inline_box}));
TestPositionType before_root = CreateTextPosition(
root, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_root);
TestPositionType middle_root = CreateTextPosition(
root, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, middle_root);
TestPositionType middle_root_upstream = CreateTextPosition(
root, 1 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, middle_root_upstream);
TestPositionType after_root = CreateTextPosition(
root, 2 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_root);
TestPositionType after_root_upstream = CreateTextPosition(
root, 2 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, after_root_upstream);
TestPositionType before_image = CreateTextPosition(
image, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_image);
TestPositionType after_image = CreateTextPosition(
image, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_image);
TestPositionType before_paragraph = CreateTextPosition(
paragraph, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_paragraph);
TestPositionType after_paragraph = CreateTextPosition(
paragraph, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_paragraph);
TestPositionType after_paragraph_upstream = CreateTextPosition(
paragraph, 1 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, after_paragraph_upstream);
TestPositionType before_link = CreateTextPosition(
link, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_link);
TestPositionType after_link = CreateTextPosition(
link, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_link);
TestPositionType after_link_upstream = CreateTextPosition(
link, 5 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, after_link_upstream);
TestPositionType before_inline_box = CreateTextPosition(
inline_box, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_inline_box);
TestPositionType after_inline_box = CreateTextPosition(
inline_box, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_inline_box);
EXPECT_EQ(*before_root->AsLeafTextPosition(), *before_image);
EXPECT_EQ(*middle_root->AsLeafTextPosition(), *before_inline_box);
EXPECT_EQ(*middle_root_upstream->AsLeafTextPosition(), *after_image);
EXPECT_EQ(*after_root->AsLeafTextPosition(), *after_inline_box);
EXPECT_EQ(*after_root_upstream->AsLeafTextPosition(), *after_inline_box);
EXPECT_EQ(*before_paragraph->AsLeafTextPosition(), *before_inline_box);
EXPECT_EQ(*after_paragraph->AsLeafTextPosition(), *after_inline_box);
EXPECT_EQ(*after_paragraph_upstream->AsLeafTextPosition(), *after_inline_box);
EXPECT_EQ(*before_link->AsLeafTextPosition(), *before_inline_box);
EXPECT_EQ(*after_link->AsLeafTextPosition(), *after_inline_box);
EXPECT_EQ(*after_link_upstream->AsLeafTextPosition(), *after_inline_box);
}
TEST_F(AXPositionTest, AsUnignoredPosition) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData static_text_data_1;
static_text_data_1.id = 2;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.SetName("1");
AXNodeData inline_box_data_1;
inline_box_data_1.id = 3;
inline_box_data_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_1.SetName("1");
AXNodeData inline_box_data_2;
inline_box_data_2.id = 4;
inline_box_data_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_2.SetName("2");
inline_box_data_2.AddState(ax::mojom::State::kIgnored);
AXNodeData container_data;
container_data.id = 5;
container_data.role = ax::mojom::Role::kGenericContainer;
container_data.AddState(ax::mojom::State::kIgnored);
AXNodeData static_text_data_2;
static_text_data_2.id = 6;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName("3");
AXNodeData inline_box_data_3;
inline_box_data_3.id = 7;
inline_box_data_3.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_3.SetName("3");
static_text_data_1.child_ids = {inline_box_data_1.id, inline_box_data_2.id};
container_data.child_ids = {static_text_data_2.id};
static_text_data_2.child_ids = {inline_box_data_3.id};
root_data.child_ids = {static_text_data_1.id, container_data.id};
SetTree(CreateAXTree({root_data, static_text_data_1, inline_box_data_1,
inline_box_data_2, container_data, static_text_data_2,
inline_box_data_3}));
TestPositionType text_position =
CreateTextPosition(container_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
TestPositionType test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(root_data.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(container_data, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(root_data.id, test_position->anchor_id());
EXPECT_EQ(2, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
TestPositionType tree_position =
CreateTreePosition(container_data, 0 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position = CreateTreePosition(container_data, 1 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(static_text_data_1, 2 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_1.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
root_data.AddState(ax::mojom::State::kIgnored);
SetTree(CreateAXTree({root_data, static_text_data_1, inline_box_data_1,
inline_box_data_2, container_data, static_text_data_2,
inline_box_data_3}));
ax_tree()->root()->UpdateUnignoredCachedValues();
text_position = CreateTextPosition(root_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_1.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_1.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position = CreateTreePosition(root_data, 1 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position = CreateTreePosition(root_data, 2 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(container_data, 0 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position = CreateTreePosition(container_data, 1 );
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
text_position = CreateTextPosition(root_data, 1 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(inline_box_data_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(inline_box_data_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(text_position->IsIgnored());
test_position = text_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_1.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
tree_position =
CreateTreePosition(inline_box_data_2, AXNodePosition::BEFORE_TEXT);
EXPECT_TRUE(tree_position->IsIgnored());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveForward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = tree_position->AsUnignoredPosition(
AXPositionAdjustmentBehavior::kMoveBackward);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box_data_1.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtTextBoundaryContentStartEndIsIgnored) {
constexpr AXNodeID kRootId = 1;
constexpr AXNodeID kStaticText1Id = 2;
constexpr AXNodeID kStaticText2Id = 3;
constexpr AXNodeID kStaticText3Id = 4;
constexpr AXNodeID kStaticText4Id = 5;
constexpr AXNodeID kInlineBox1Id = 6;
constexpr AXNodeID kInlineBox2Id = 7;
constexpr AXNodeID kInlineBox3Id = 8;
constexpr AXNodeID kInlineBox4Id = 9;
AXNodeData root_data;
root_data.id = kRootId;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData static_text_data_1;
static_text_data_1.id = kStaticText1Id;
static_text_data_1.role = ax::mojom::Role::kStaticText;
static_text_data_1.SetName("One");
AXNodeData inline_box_data_1;
inline_box_data_1.id = kInlineBox1Id;
inline_box_data_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_1.SetName("One");
inline_box_data_1.AddState(ax::mojom::State::kIgnored);
inline_box_data_1.AddIntListAttribute(
ax::mojom::IntListAttribute::kWordStarts, {0});
inline_box_data_1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
{3});
inline_box_data_1.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
kInlineBox2Id);
AXNodeData static_text_data_2;
static_text_data_2.id = kStaticText2Id;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName("Two");
AXNodeData inline_box_data_2;
inline_box_data_2.id = kInlineBox2Id;
inline_box_data_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_2.SetName("Two");
inline_box_data_2.AddIntListAttribute(
ax::mojom::IntListAttribute::kWordStarts, {0});
inline_box_data_2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
{3});
inline_box_data_2.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
kInlineBox1Id);
inline_box_data_2.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
kInlineBox3Id);
AXNodeData static_text_data_3;
static_text_data_3.id = kStaticText3Id;
static_text_data_3.role = ax::mojom::Role::kStaticText;
static_text_data_3.SetName("Three");
AXNodeData inline_box_data_3;
inline_box_data_3.id = kInlineBox3Id;
inline_box_data_3.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_3.SetName("Three");
inline_box_data_3.AddIntListAttribute(
ax::mojom::IntListAttribute::kWordStarts, {0});
inline_box_data_3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
{5});
inline_box_data_3.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
kInlineBox2Id);
inline_box_data_3.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
kInlineBox4Id);
AXNodeData static_text_data_4;
static_text_data_4.id = kStaticText4Id;
static_text_data_4.role = ax::mojom::Role::kStaticText;
static_text_data_4.SetName("Four");
AXNodeData inline_box_data_4;
inline_box_data_4.id = kInlineBox4Id;
inline_box_data_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_data_4.SetName("Four");
inline_box_data_4.AddState(ax::mojom::State::kIgnored);
inline_box_data_3.AddIntListAttribute(
ax::mojom::IntListAttribute::kWordStarts, {0});
inline_box_data_3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
{4});
inline_box_data_3.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
kInlineBox3Id);
root_data.child_ids = {static_text_data_1.id, static_text_data_2.id,
static_text_data_3.id, static_text_data_4.id};
static_text_data_1.child_ids = {inline_box_data_1.id};
static_text_data_2.child_ids = {inline_box_data_2.id};
static_text_data_3.child_ids = {inline_box_data_3.id};
static_text_data_4.child_ids = {inline_box_data_4.id};
SetTree(
CreateAXTree({root_data, static_text_data_1, static_text_data_2,
static_text_data_3, static_text_data_4, inline_box_data_1,
inline_box_data_2, inline_box_data_3, inline_box_data_4}));
TestPositionType text_position =
CreateTextPosition(inline_box_data_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(text_position->IsIgnored());
TestPositionType test_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kWordStart, ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kWordStart, ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_2.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(inline_box_data_3, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(text_position->IsIgnored());
test_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kWordStart, ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_3.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kWordStart, ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box_data_2.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreatePositionAtInvalidGraphemeBoundary) {
std::vector<int> text_offsets;
SetTree(CreateMultilingualDocument(&text_offsets));
TestPositionType test_position =
CreateTextPosition(*GetTree()->root(), 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(4, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 10 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(10, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfAnchorWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position =
null_position->CreatePositionAtStartOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfAnchorWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position =
tree_position->CreatePositionAtStartOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(inline_box1_, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfAnchorWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->CreatePositionAtStartOfAnchor();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(inline_box1_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePositionAtStartOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfAnchorWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreatePositionAtEndOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfAnchorWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 3 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->CreatePositionAtEndOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->child_index());
tree_position = CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfAnchorWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreatePositionAtEndOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(inline_box1_, 5 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePositionAtEndOfAnchor();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreatePositionAtPreviousFormatStartWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position =
null_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtPreviousFormatStartWithTreePosition) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType tree_position =
CreateTreePosition(static_text1_, 1 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
TestPositionType test_position =
tree_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(static_text1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtPreviousFormatStartWithTextPosition) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType text_position = CreateTextPosition(
inline_box1_, 2 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtNextFormatEndWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtNextFormatEndWithTreePosition) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType tree_position =
CreateTreePosition(button_, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
TestPositionType test_position = tree_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtNextFormatEndWithTextPosition) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType text_position = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = test_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtNextFormatEndOnEmbeddedObject) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
root_1.id = 1;
root_1.role = ax::mojom::Role::kRootWebArea;
AXNodeData heading_2;
heading_2.id = 2;
heading_2.role = ax::mojom::Role::kHeading;
AXNodeData static_text_3;
static_text_3.id = 3;
static_text_3.role = ax::mojom::Role::kStaticText;
static_text_3.SetName("heading 1");
AXNodeData inline_text_4;
inline_text_4.id = 4;
inline_text_4.role = ax::mojom::Role::kInlineTextBox;
inline_text_4.SetName("heading 1");
AXNodeData popup_button_5;
popup_button_5.id = 5;
popup_button_5.role = ax::mojom::Role::kComboBoxSelect;
popup_button_5.AddState(ax::mojom::State::kCollapsed);
popup_button_5.SetName("option 1");
AXNodeData menu_list_popup_6;
menu_list_popup_6.id = 6;
menu_list_popup_6.role = ax::mojom::Role::kMenuListPopup;
menu_list_popup_6.AddState(ax::mojom::State::kInvisible);
AXNodeData menu_list_option_7;
menu_list_option_7.id = 7;
menu_list_option_7.role = ax::mojom::Role::kMenuListOption;
menu_list_option_7.AddState(ax::mojom::State::kInvisible);
menu_list_option_7.SetName("option 1");
AXNodeData heading_8;
heading_8.id = 8;
heading_8.role = ax::mojom::Role::kHeading;
AXNodeData static_text_9;
static_text_9.id = 9;
static_text_9.role = ax::mojom::Role::kStaticText;
static_text_9.SetName("heading 2");
AXNodeData inline_text_10;
inline_text_10.id = 10;
inline_text_10.role = ax::mojom::Role::kInlineTextBox;
inline_text_10.SetName("heading 2");
AXNodeData popup_button_11;
popup_button_11.id = 11;
popup_button_11.role = ax::mojom::Role::kComboBoxSelect;
popup_button_11.AddState(ax::mojom::State::kCollapsed);
popup_button_11.SetName("option 2");
AXNodeData menu_list_popup_12;
menu_list_popup_12.id = 12;
menu_list_popup_12.role = ax::mojom::Role::kMenuListPopup;
menu_list_popup_12.AddState(ax::mojom::State::kInvisible);
AXNodeData menu_list_option_13;
menu_list_option_13.id = 13;
menu_list_option_13.role = ax::mojom::Role::kMenuListOption;
menu_list_option_13.AddState(ax::mojom::State::kInvisible);
menu_list_option_13.SetName("option 2");
AXNodeData popup_button_14;
popup_button_14.id = 14;
popup_button_14.role = ax::mojom::Role::kComboBoxSelect;
popup_button_14.AddState(ax::mojom::State::kCollapsed);
popup_button_14.SetName("option 3");
AXNodeData menu_list_popup_15;
menu_list_popup_15.id = 15;
menu_list_popup_15.role = ax::mojom::Role::kMenuListPopup;
menu_list_popup_15.AddState(ax::mojom::State::kInvisible);
AXNodeData menu_list_option_16;
menu_list_option_16.id = 16;
menu_list_option_16.role = ax::mojom::Role::kMenuListOption;
menu_list_option_16.AddState(ax::mojom::State::kInvisible);
menu_list_option_16.SetName("option 3");
AXNodeData static_text_17;
static_text_17.id = 17;
static_text_17.role = ax::mojom::Role::kStaticText;
static_text_17.SetName("more text");
AXNodeData inline_text_18;
inline_text_18.id = 18;
inline_text_18.role = ax::mojom::Role::kInlineTextBox;
inline_text_18.SetName("more text");
root_1.child_ids = {heading_2.id, popup_button_5.id,
heading_8.id, popup_button_11.id,
popup_button_14.id, static_text_17.id};
heading_2.child_ids = {static_text_3.id};
static_text_3.child_ids = {inline_text_4.id};
popup_button_5.child_ids = {menu_list_popup_6.id};
menu_list_popup_6.child_ids = {menu_list_option_7.id};
heading_8.child_ids = {static_text_9.id};
static_text_9.child_ids = {inline_text_10.id};
popup_button_11.child_ids = {menu_list_popup_12.id};
menu_list_popup_12.child_ids = {menu_list_option_13.id};
popup_button_14.child_ids = {menu_list_popup_15.id};
menu_list_popup_15.child_ids = {menu_list_option_16.id};
static_text_17.child_ids = {inline_text_18.id};
SetTree(CreateAXTree(
{root_1, heading_2, static_text_3, inline_text_4, popup_button_5,
menu_list_popup_6, menu_list_option_7, heading_8, static_text_9,
inline_text_10, popup_button_11, menu_list_popup_12, menu_list_option_13,
popup_button_14, menu_list_popup_15, menu_list_option_16, static_text_17,
inline_text_18}));
TestPositionType text_position = CreateTextPosition(
inline_text_4, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType format_end_position =
text_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, format_end_position);
EXPECT_TRUE(format_end_position->IsTextPosition());
EXPECT_EQ(inline_text_4.id, format_end_position->anchor_id());
EXPECT_EQ(9, format_end_position->text_offset());
EXPECT_EQ("heading 1", format_end_position->GetAnchor()->GetStringAttribute(
ax::mojom::StringAttribute::kName));
format_end_position = format_end_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, format_end_position);
EXPECT_TRUE(format_end_position->IsTextPosition());
EXPECT_EQ(popup_button_5.id, format_end_position->anchor_id());
EXPECT_EQ(1, format_end_position->text_offset());
EXPECT_EQ("option 1", format_end_position->GetAnchor()->GetStringAttribute(
ax::mojom::StringAttribute::kName));
format_end_position = format_end_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, format_end_position);
EXPECT_TRUE(format_end_position->IsTextPosition());
EXPECT_EQ(inline_text_10.id, format_end_position->anchor_id());
EXPECT_EQ(9, format_end_position->text_offset());
EXPECT_EQ("heading 2", format_end_position->GetAnchor()->GetStringAttribute(
ax::mojom::StringAttribute::kName));
format_end_position = format_end_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, format_end_position);
EXPECT_TRUE(format_end_position->IsTextPosition());
EXPECT_EQ(popup_button_11.id, format_end_position->anchor_id());
EXPECT_EQ(1, format_end_position->text_offset());
EXPECT_EQ("option 2", format_end_position->GetAnchor()->GetStringAttribute(
ax::mojom::StringAttribute::kName));
format_end_position = format_end_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, format_end_position);
EXPECT_TRUE(format_end_position->IsTextPosition());
EXPECT_EQ(popup_button_14.id, format_end_position->anchor_id());
EXPECT_EQ(1, format_end_position->text_offset());
EXPECT_EQ("option 3", format_end_position->GetAnchor()->GetStringAttribute(
ax::mojom::StringAttribute::kName));
format_end_position = format_end_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, format_end_position);
EXPECT_TRUE(format_end_position->IsTextPosition());
EXPECT_EQ(inline_text_18.id, format_end_position->anchor_id());
EXPECT_EQ(9, format_end_position->text_offset());
EXPECT_EQ("more text", format_end_position->GetAnchor()->GetStringAttribute(
ax::mojom::StringAttribute::kName));
}
TEST_F(AXPositionTest, CreatePositionAtFormatBoundaryWithTextPosition) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_data;
text_data.id = 2;
text_data.role = ax::mojom::Role::kStaticText;
text_data.SetName("some text");
AXNodeData more_text_data;
more_text_data.id = 3;
more_text_data.role = ax::mojom::Role::kStaticText;
more_text_data.SetName("more text");
root_data.child_ids = {text_data.id, more_text_data.id};
SetTree(CreateAXTree({root_data, text_data, more_text_data}));
TestPositionType text_position = CreateTextPosition(
text_data, 8 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position =
text_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(more_text_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(more_text_data.id, test_position->anchor_id());
EXPECT_EQ(9, test_position->text_offset());
}
TEST_F(AXPositionTest, MoveByFormatWithIgnoredNodes) {
AXNodeData root_1;
AXNodeData generic_container_2;
AXNodeData button_3;
AXNodeData static_text_4;
AXNodeData inline_box_5;
AXNodeData svg_root_6;
AXNodeData generic_container_7;
AXNodeData generic_container_8;
AXNodeData heading_9;
AXNodeData static_text_10;
AXNodeData inline_box_11;
AXNodeData static_text_12;
AXNodeData inline_box_13;
AXNodeData generic_container_14;
AXNodeData generic_container_15;
AXNodeData heading_16;
AXNodeData static_text_17;
AXNodeData inline_box_18;
AXNodeData generic_container_19;
AXNodeData generic_container_20;
AXNodeData static_text_21;
AXNodeData inline_box_22;
AXNodeData heading_23;
AXNodeData static_text_24;
AXNodeData inline_box_25;
root_1.id = 1;
generic_container_2.id = 2;
button_3.id = 3;
static_text_4.id = 4;
inline_box_5.id = 5;
svg_root_6.id = 6;
generic_container_7.id = 7;
generic_container_8.id = 8;
heading_9.id = 9;
static_text_10.id = 10;
inline_box_11.id = 11;
static_text_12.id = 12;
inline_box_13.id = 13;
generic_container_14.id = 14;
generic_container_15.id = 15;
heading_16.id = 16;
static_text_17.id = 17;
inline_box_18.id = 18;
generic_container_19.id = 19;
generic_container_20.id = 20;
static_text_21.id = 21;
inline_box_22.id = 22;
heading_23.id = 23;
static_text_24.id = 24;
inline_box_25.id = 25;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {generic_container_2.id, generic_container_8.id,
generic_container_15.id, generic_container_19.id};
generic_container_2.role = ax::mojom::Role::kGenericContainer;
generic_container_2.child_ids = {button_3.id};
button_3.role = ax::mojom::Role::kButton;
button_3.child_ids = {static_text_4.id, svg_root_6.id};
static_text_4.role = ax::mojom::Role::kStaticText;
static_text_4.child_ids = {inline_box_5.id};
static_text_4.SetName("Button");
inline_box_5.role = ax::mojom::Role::kInlineTextBox;
inline_box_5.SetName("Button");
svg_root_6.role = ax::mojom::Role::kSvgRoot;
svg_root_6.child_ids = {generic_container_7.id};
svg_root_6.AddState(ax::mojom::State::kIgnored);
generic_container_7.role = ax::mojom::Role::kGenericContainer;
generic_container_7.AddState(ax::mojom::State::kIgnored);
generic_container_8.role = ax::mojom::Role::kGenericContainer;
generic_container_8.child_ids = {heading_9.id, static_text_12.id,
generic_container_14.id};
heading_9.role = ax::mojom::Role::kHeading;
heading_9.child_ids = {static_text_10.id};
static_text_10.role = ax::mojom::Role::kStaticText;
static_text_10.child_ids = {inline_box_11.id};
static_text_10.SetName("Heading");
inline_box_11.role = ax::mojom::Role::kInlineTextBox;
inline_box_11.SetName("Heading");
static_text_12.role = ax::mojom::Role::kStaticText;
static_text_12.child_ids = {inline_box_13.id};
static_text_12.SetName("3.14");
inline_box_13.role = ax::mojom::Role::kInlineTextBox;
inline_box_13.SetName("3.14");
generic_container_14.role = ax::mojom::Role::kGenericContainer;
generic_container_14.AddState(ax::mojom::State::kIgnored);
generic_container_15.role = ax::mojom::Role::kGenericContainer;
generic_container_15.child_ids = {heading_16.id};
heading_16.role = ax::mojom::Role::kHeading;
heading_16.child_ids = {static_text_17.id};
static_text_17.role = ax::mojom::Role::kStaticText;
static_text_17.child_ids = {inline_box_18.id};
static_text_17.SetName("Heading");
inline_box_18.role = ax::mojom::Role::kInlineTextBox;
inline_box_18.SetName("Heading");
generic_container_19.role = ax::mojom::Role::kGenericContainer;
generic_container_19.child_ids = {generic_container_20.id, static_text_21.id,
heading_23.id};
generic_container_20.role = ax::mojom::Role::kGenericContainer;
generic_container_20.AddState(ax::mojom::State::kIgnored);
static_text_21.role = ax::mojom::Role::kStaticText;
static_text_21.child_ids = {inline_box_22.id};
static_text_21.SetName("3.14");
inline_box_22.role = ax::mojom::Role::kInlineTextBox;
inline_box_22.SetName("3.14");
heading_23.role = ax::mojom::Role::kHeading;
heading_23.child_ids = {static_text_24.id};
static_text_24.role = ax::mojom::Role::kStaticText;
static_text_24.child_ids = {inline_box_25.id};
static_text_24.SetName("Heading");
inline_box_25.role = ax::mojom::Role::kInlineTextBox;
inline_box_25.SetName("Heading");
SetTree(CreateAXTree({root_1,
generic_container_2,
button_3,
static_text_4,
inline_box_5,
svg_root_6,
generic_container_7,
generic_container_8,
heading_9,
static_text_10,
inline_box_11,
static_text_12,
inline_box_13,
generic_container_14,
generic_container_15,
heading_16,
static_text_17,
inline_box_18,
generic_container_19,
generic_container_20,
static_text_21,
inline_box_22,
heading_23,
static_text_24,
inline_box_25}));
{
TestPositionType text_position =
CreateTextPosition(inline_box_5, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_5.id, text_position->anchor_id());
EXPECT_EQ(6, text_position->text_offset());
text_position = text_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_11.id, text_position->anchor_id());
EXPECT_EQ(7, text_position->text_offset());
text_position = CreateTextPosition(inline_box_11, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_11.id, text_position->anchor_id());
EXPECT_EQ(0, text_position->text_offset());
text_position = text_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_5.id, text_position->anchor_id());
EXPECT_EQ(0, text_position->text_offset());
}
{
TestPositionType text_position =
CreateTextPosition(inline_box_11, 7 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_11.id, text_position->anchor_id());
EXPECT_EQ(7, text_position->text_offset());
text_position = text_position->CreateNextFormatEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_13.id, text_position->anchor_id());
EXPECT_EQ(4, text_position->text_offset());
text_position = CreateTextPosition(inline_box_25, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_25.id, text_position->anchor_id());
EXPECT_EQ(0, text_position->text_offset());
text_position = text_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(inline_box_22.id, text_position->anchor_id());
EXPECT_EQ(0, text_position->text_offset());
}
}
TEST_F(AXPositionTest, CreatePositionAtPageBoundaryWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position =
null_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtPageBoundaryWithTreePosition) {
AXNodeData root_data, page_1_data, page_1_text_data, page_2_data,
page_2_text_data, page_3_data, page_3_text_data;
SetTree(CreateMultipageDocument(root_data, page_1_data, page_1_text_data,
page_2_data, page_2_text_data, page_3_data,
page_3_text_data));
TestPositionType tree_position =
CreateTreePosition(page_1_data, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
TestPositionType test_position = tree_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_1_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = tree_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = tree_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = tree_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_1_data.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->child_index());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_3_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_3_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
TestPositionType null_position = test_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
null_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
tree_position = test_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, tree_position);
EXPECT_TRUE(tree_position->IsTreePosition());
EXPECT_EQ(page_3_text_data.id, tree_position->anchor_id());
EXPECT_EQ(0, tree_position->child_index());
test_position = tree_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = tree_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
test_position = test_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
null_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
null_position = test_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtPageBoundaryWithTextPosition) {
AXNodeData root_data, page_1_data, page_1_text_data, page_2_data,
page_2_text_data, page_3_data, page_3_text_data;
SetTree(CreateMultipageDocument(root_data, page_1_data, page_1_text_data,
page_2_data, page_2_text_data, page_3_data,
page_3_text_data));
TestPositionType text_position =
CreateTextPosition(page_1_text_data, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(19, test_position->text_offset());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_3_text_data.id, test_position->anchor_id());
EXPECT_EQ(24, test_position->text_offset());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_3_text_data.id, test_position->anchor_id());
EXPECT_EQ(24, test_position->text_offset());
test_position = test_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_3_text_data.id, test_position->anchor_id());
EXPECT_EQ(24, test_position->text_offset());
test_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_3_text_data.id, test_position->anchor_id());
EXPECT_EQ(24, test_position->text_offset());
TestPositionType null_position = test_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
null_position = test_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
text_position = test_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(page_3_text_data.id, text_position->anchor_id());
EXPECT_EQ(24, text_position->text_offset());
test_position = text_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(19, test_position->text_offset());
test_position = text_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(19, test_position->text_offset());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_2_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(page_1_text_data.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
null_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
null_position = test_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, null_position);
EXPECT_TRUE(null_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtPageBoundaryWithNonPaginatedDocument) {
TestPositionType text_position = CreateTextPosition(
static_text1_, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position =
text_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreatePreviousPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreateNextPageEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = test_position->CreatePreviousPageStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfAXTreeWithNullPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position =
null_position->CreatePositionAtStartOfAXTree();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
EXPECT_FALSE(test_position->AtStartOfAXTree());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfAXTreeWithTreePosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
const AXTreeID& iframe_tree_id = iframe_tree->GetAXTreeID();
TestPositionType tree_position =
CreateTreePosition(views_tree, window, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position =
tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, window, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
views_tree, back_button, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(views_tree, back_button, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
webpage_tree, paragraph, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, paragraph, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
iframe_tree, iframe_root, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position =
CreateTreePosition(iframe_tree, iframe_root, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfAXTreeWithTextPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
const AXTreeID& iframe_tree_id = iframe_tree->GetAXTreeID();
TestPositionType text_position =
CreateTextPosition(views_tree, window, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position =
text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(views_tree, window, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfAXTreeWithNullPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreatePositionAtEndOfAXTree();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
EXPECT_FALSE(test_position->AtEndOfAXTree());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfAXTreeWithTreePosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
const AXTreeID& iframe_tree_id = iframe_tree->GetAXTreeID();
TestPositionType tree_position =
CreateTreePosition(views_tree, window, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, window, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
views_tree, back_button, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(views_tree, back_button, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
webpage_tree, paragraph, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, paragraph, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
iframe_tree, iframe_root, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(iframe_tree, iframe_root, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfAXTreeWithTextPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
const AXTreeID& iframe_tree_id = iframe_tree->GetAXTreeID();
TestPositionType text_position =
CreateTextPosition(views_tree, window, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position = CreateTextPosition(views_tree, window, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(13, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfAXTree();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfAXTree());
EXPECT_EQ(iframe_tree_id, test_position->tree_id());
EXPECT_EQ(iframe_root.id, test_position->anchor_id());
EXPECT_EQ(13, test_position->text_offset());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfContentWithNullPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position =
null_position->CreatePositionAtStartOfContent();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfContentWithTreePosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
TestPositionType tree_position =
CreateTreePosition(views_tree, window, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position =
tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, window, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
views_tree, back_button, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(views_tree, back_button, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
webpage_tree, paragraph, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, paragraph, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
iframe_tree, iframe_root, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(iframe_tree, iframe_root, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtStartOfContentWithTextPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
TestPositionType text_position =
CreateTextPosition(views_tree, window, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position =
text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(views_tree, window, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(window.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtStartOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtStartOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(root_web_area.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfContentWithNullPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position =
null_position->CreatePositionAtEndOfContent();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfContentWithTreePosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
TestPositionType tree_position =
CreateTreePosition(views_tree, window, 0 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position =
tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, window, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
views_tree, back_button, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(views_tree, back_button, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(views_tree, web_view, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, root_web_area, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
webpage_tree, paragraph, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(webpage_tree, paragraph, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position = CreateTreePosition(
iframe_tree, iframe_root, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
tree_position =
CreateTreePosition(iframe_tree, iframe_root, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
}
TEST_F(AXPositionTest, CreatePositionAtEndOfContentWithTextPosition) {
AXNodeData window, back_button, web_view, root_web_area, iframe_root,
paragraph, address_bar;
std::vector<TestSingleAXTreeManager> trees;
ASSERT_NO_FATAL_FAILURE(CreateBrowserWindow(window, back_button, web_view,
root_web_area, iframe_root,
paragraph, address_bar, trees));
const AXTree* views_tree = trees[0].GetTree();
const AXTree* webpage_tree = trees[1].GetTree();
const AXTree* iframe_tree = trees[2].GetTree();
const AXTreeID& views_tree_id = views_tree->GetAXTreeID();
const AXTreeID& webpage_tree_id = webpage_tree->GetAXTreeID();
TestPositionType text_position =
CreateTextPosition(views_tree, window, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position =
text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position = CreateTextPosition(views_tree, window, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position =
CreateTextPosition(views_tree, back_button, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position = CreateTextPosition(views_tree, web_view, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(views_tree_id, test_position->tree_id());
EXPECT_EQ(address_bar.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, root_web_area, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(webpage_tree, paragraph, 12 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
text_position =
CreateTextPosition(iframe_tree, iframe_root, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreatePositionAtEndOfContent();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_TRUE(test_position->AtEndOfContent());
EXPECT_EQ(webpage_tree_id, test_position->tree_id());
EXPECT_EQ(paragraph.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
}
TEST_F(AXPositionTest, CreateChildPositionAtWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateChildPositionAt(0);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreateChildPositionAtWithTreePosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 2 );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->CreateChildPositionAt(1);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(AXNodePosition::BEFORE_TEXT, test_position->child_index());
tree_position = CreateTreePosition(button_, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreateChildPositionAt(0);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreateChildPositionAtWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
static_text1_, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreateChildPositionAt(0);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(static_text2_, 4 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateChildPositionAt(1);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreateParentPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreateParentPositionWithTreePosition) {
TestPositionType tree_position = CreateTreePosition(
check_box_, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
TestPositionType test_position = tree_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->child_index());
tree_position = CreateTreePosition(check_box_, 0 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(2, test_position->child_index());
tree_position = CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, tree_position);
test_position = tree_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition())
<< "We should cross into a minimalistic Views tree.";
tree_position = CreateTreePosition(
inline_box2_, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
test_position = tree_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(static_text2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->child_index());
test_position = test_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(2, test_position->child_index());
tree_position = CreateTreePosition(inline_box2_, 0 );
ASSERT_NE(nullptr, tree_position);
ASSERT_TRUE(tree_position->IsTreePosition());
test_position = tree_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(static_text2_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->child_index());
test_position = test_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->child_index());
}
TEST_F(AXPositionTest, CreateParentPositionWithTextPosition) {
TestPositionType text_position = CreateTextPosition(
check_box_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(root_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(root_, 2 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
test_position = text_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition())
<< "We should cross into a minimalistic Views tree.";
text_position = CreateTextPosition(inline_box2_, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(static_text2_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = test_position->CreateParentPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreateParentPositionWithMoveDirection) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData link_2;
AXNodeData static_text_3;
AXNodeData inline_box_4;
AXNodeData paragraph_5;
AXNodeData static_text_6;
AXNodeData inline_box_7;
root_1.id = 1;
link_2.id = 2;
static_text_3.id = 3;
inline_box_4.id = 4;
paragraph_5.id = 5;
static_text_6.id = 6;
inline_box_7.id = 7;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {link_2.id};
root_1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
link_2.role = ax::mojom::Role::kLink;
link_2.child_ids = {static_text_3.id, paragraph_5.id};
static_text_3.role = ax::mojom::Role::kStaticText;
static_text_3.child_ids = {inline_box_4.id};
static_text_3.SetName("Hello");
inline_box_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_4.SetName("Hello");
paragraph_5.role = ax::mojom::Role::kParagraph;
paragraph_5.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph_5.child_ids = {static_text_6.id};
static_text_6.role = ax::mojom::Role::kStaticText;
static_text_6.child_ids = {inline_box_7.id};
static_text_6.SetName("world.");
inline_box_7.role = ax::mojom::Role::kInlineTextBox;
inline_box_7.SetName("world.");
SetTree(CreateAXTree({root_1, link_2, static_text_3, inline_box_4,
paragraph_5, static_text_6, inline_box_7}));
TestPositionType tree_position = CreateTreePosition(
inline_box_4, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
TestPositionType ancestor_position = tree_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTreePosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->child_index());
tree_position = CreateTreePosition(
inline_box_4, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, tree_position);
ancestor_position = tree_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kBackward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTreePosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->child_index());
tree_position = CreateTreePosition(inline_box_4, 0 );
ASSERT_NE(nullptr, tree_position);
ancestor_position = tree_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTreePosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(1, ancestor_position->child_index());
tree_position = CreateTreePosition(inline_box_4, 0 );
ASSERT_NE(nullptr, tree_position);
ancestor_position = tree_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kBackward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTreePosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->child_index());
tree_position = CreateTreePosition(inline_box_7, 0 );
ASSERT_NE(nullptr, tree_position);
ancestor_position = tree_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTreePosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(1, ancestor_position->child_index());
tree_position = CreateTreePosition(inline_box_7, 0 );
ASSERT_NE(nullptr, tree_position);
ancestor_position = tree_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kBackward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTreePosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(1, ancestor_position->child_index());
TestPositionType text_position = CreateTextPosition(
inline_box_4, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ancestor_position = text_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTextPosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream,
ancestor_position->affinity());
text_position = CreateTextPosition(inline_box_4, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ancestor_position = text_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kBackward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTextPosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream,
ancestor_position->affinity());
text_position = CreateTextPosition(inline_box_4, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ancestor_position = text_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTextPosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(1, ancestor_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream,
ancestor_position->affinity());
text_position = CreateTextPosition(inline_box_4, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ancestor_position = text_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kBackward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTextPosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream,
ancestor_position->affinity());
text_position = CreateTextPosition(inline_box_7, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ancestor_position = text_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kForward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTextPosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(1, ancestor_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream,
ancestor_position->affinity());
text_position = CreateTextPosition(inline_box_7, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ancestor_position = text_position->CreateAncestorPosition(
GetRoot(), ax::mojom::MoveDirection::kBackward);
ASSERT_NE(nullptr, ancestor_position);
EXPECT_TRUE(ancestor_position->IsTextPosition());
EXPECT_EQ(root_1.id, ancestor_position->anchor_id());
EXPECT_EQ(0, ancestor_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream,
ancestor_position->affinity());
}
TEST_F(AXPositionTest, CreateParentAndLeafPositionWithIgnoredNodes) {
AXNodeData root;
AXNodeData generic_container_ignored;
AXNodeData static_text_1;
AXNodeData inline_box_1;
AXNodeData static_text_ignored_1;
AXNodeData inline_box_ignored_1;
AXNodeData static_text_ignored_2;
AXNodeData inline_box_ignored_2;
AXNodeData static_text_2;
AXNodeData inline_box_2;
root.id = 1;
generic_container_ignored.id = 2;
static_text_1.id = 3;
inline_box_1.id = 4;
static_text_2.id = 5;
inline_box_2.id = 6;
static_text_ignored_1.id = 7;
inline_box_ignored_1.id = 8;
static_text_ignored_2.id = 9;
inline_box_ignored_2.id = 10;
root.role = ax::mojom::Role::kRootWebArea;
root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
root.child_ids = {generic_container_ignored.id, static_text_ignored_1.id,
static_text_ignored_2.id, static_text_2.id};
generic_container_ignored.role = ax::mojom::Role::kGenericContainer;
generic_container_ignored.AddState(ax::mojom::State::kIgnored);
generic_container_ignored.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
generic_container_ignored.child_ids = {static_text_1.id};
static_text_1.role = ax::mojom::Role::kStaticText;
static_text_1.SetName("Hello");
static_text_1.child_ids = {inline_box_1.id};
inline_box_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_1.SetName("Hello");
static_text_ignored_1.role = ax::mojom::Role::kStaticText;
static_text_ignored_1.AddState(ax::mojom::State::kIgnored);
static_text_ignored_1.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_ignored_1.SetName("Ignored1");
static_text_ignored_1.child_ids = {inline_box_ignored_1.id};
inline_box_ignored_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_ignored_1.AddState(ax::mojom::State::kIgnored);
inline_box_ignored_1.SetName("Ignored1");
static_text_ignored_2.role = ax::mojom::Role::kStaticText;
static_text_ignored_2.AddState(ax::mojom::State::kIgnored);
static_text_ignored_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_ignored_2.SetName("Ignored2");
static_text_ignored_2.child_ids = {inline_box_ignored_2.id};
inline_box_ignored_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_ignored_2.AddState(ax::mojom::State::kIgnored);
inline_box_ignored_2.SetName("Ignored2");
static_text_2.role = ax::mojom::Role::kStaticText;
static_text_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_2.SetName("World");
static_text_2.child_ids = {inline_box_2.id};
inline_box_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_2.SetName("World");
SetTree(CreateAXTree({root, generic_container_ignored, static_text_1,
inline_box_1, static_text_ignored_1,
inline_box_ignored_1, static_text_ignored_2,
inline_box_ignored_2, static_text_2, inline_box_2}));
TestPositionType before_root = CreateTextPosition(
root, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_root->IsNullPosition());
TestPositionType middle_root = CreateTextPosition(
root, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(middle_root->IsNullPosition());
TestPositionType middle_root_upstream = CreateTextPosition(
root, 5 , ax::mojom::TextAffinity::kUpstream);
ASSERT_FALSE(middle_root_upstream->IsNullPosition());
TestPositionType after_root = CreateTextPosition(
root, 10 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_root->IsNullPosition());
TestPositionType before_inline_box_1 = CreateTextPosition(
inline_box_1, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_1->IsNullPosition());
TestPositionType after_inline_box_1 = CreateTextPosition(
inline_box_1, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_inline_box_1->IsNullPosition());
TestPositionType before_inline_box_ignored_1 =
CreateTextPosition(inline_box_ignored_1, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_ignored_1->IsNullPosition());
ASSERT_TRUE(before_inline_box_ignored_1->IsIgnored());
TestPositionType before_inline_box_ignored_1_tree = CreateTreePosition(
inline_box_ignored_1, AXNodePosition::BEFORE_TEXT );
ASSERT_FALSE(before_inline_box_ignored_1_tree->IsNullPosition());
ASSERT_TRUE(before_inline_box_ignored_1_tree->IsIgnored());
TestPositionType after_inline_box_ignored_1_tree =
CreateTreePosition(inline_box_ignored_1, 0 );
ASSERT_FALSE(after_inline_box_ignored_1_tree->IsNullPosition());
ASSERT_TRUE(after_inline_box_ignored_1_tree->IsIgnored());
TestPositionType before_inline_box_ignored_2 =
CreateTextPosition(inline_box_ignored_2, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_ignored_2->IsNullPosition());
ASSERT_TRUE(before_inline_box_ignored_2->IsIgnored());
TestPositionType before_inline_box_ignored_2_tree = CreateTreePosition(
inline_box_ignored_2, AXNodePosition::BEFORE_TEXT );
ASSERT_FALSE(before_inline_box_ignored_2_tree->IsNullPosition());
ASSERT_TRUE(before_inline_box_ignored_2_tree->IsIgnored());
TestPositionType after_inline_box_ignored_2_tree =
CreateTreePosition(inline_box_ignored_2, 0 );
ASSERT_FALSE(after_inline_box_ignored_2_tree->IsNullPosition());
ASSERT_TRUE(after_inline_box_ignored_2_tree->IsIgnored());
TestPositionType before_inline_box_2 = CreateTextPosition(
inline_box_2, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_2->IsNullPosition());
TestPositionType after_inline_box_2 = CreateTextPosition(
inline_box_2, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_inline_box_2->IsNullPosition());
TestPositionType parent_position =
before_inline_box_1->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(generic_container_ignored.id, parent_position->anchor_id());
EXPECT_EQ(0, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
TestPositionType leaf_position = before_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_1.id, leaf_position->anchor_id());
EXPECT_EQ(0, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
after_inline_box_1->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsIgnored());
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(generic_container_ignored.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position = parent_position->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_FALSE(parent_position->IsIgnored());
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
leaf_position = middle_root_upstream->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_1.id, leaf_position->anchor_id());
EXPECT_EQ(5, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position = before_inline_box_ignored_1->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position = before_inline_box_ignored_1_tree->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(1, parent_position->child_index());
parent_position = after_inline_box_ignored_1_tree->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(2, parent_position->child_index());
parent_position = before_inline_box_ignored_2->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position = before_inline_box_ignored_2_tree->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(2, parent_position->child_index());
parent_position = after_inline_box_ignored_2_tree->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(3, parent_position->child_index());
parent_position =
before_inline_box_2->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
leaf_position = middle_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_2.id, leaf_position->anchor_id());
EXPECT_EQ(0, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
after_inline_box_2->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(10, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
leaf_position = after_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_2.id, leaf_position->anchor_id());
EXPECT_EQ(5, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
}
TEST_F(AXPositionTest, CreateParentAndLeafPositionWithEmptyNodes) {
AXNodeData root;
AXNodeData link;
AXNodeData static_text_1;
AXNodeData inline_box_1;
AXNodeData static_text_empty;
AXNodeData inline_box_empty;
AXNodeData button_empty;
AXNodeData static_text_2;
AXNodeData inline_box_2;
root.id = 1;
link.id = 2;
static_text_1.id = 3;
inline_box_1.id = 4;
static_text_empty.id = 5;
inline_box_empty.id = 6;
button_empty.id = 7;
static_text_2.id = 8;
inline_box_2.id = 9;
root.role = ax::mojom::Role::kRootWebArea;
root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
root.child_ids = {link.id, static_text_empty.id, button_empty.id,
static_text_2.id};
link.role = ax::mojom::Role::kLink;
link.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
link.child_ids = {static_text_1.id};
static_text_1.role = ax::mojom::Role::kStaticText;
static_text_1.SetName("Hello");
static_text_1.child_ids = {inline_box_1.id};
inline_box_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_1.SetName("Hello");
static_text_empty.role = ax::mojom::Role::kStaticText;
static_text_empty.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_empty.child_ids = {inline_box_empty.id};
inline_box_empty.role = ax::mojom::Role::kInlineTextBox;
button_empty.role = ax::mojom::Role::kButton;
button_empty.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
static_text_2.role = ax::mojom::Role::kStaticText;
static_text_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_2.SetName("World");
static_text_2.child_ids = {inline_box_2.id};
inline_box_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_2.SetName("World");
SetTree(CreateAXTree({root, link, static_text_1, inline_box_1,
static_text_empty, inline_box_empty, button_empty,
static_text_2, inline_box_2}));
TestPositionType before_root = CreateTextPosition(
root, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_root->IsNullPosition());
TestPositionType middle_root = CreateTextPosition(
root, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(middle_root->IsNullPosition());
TestPositionType middle_root_upstream = CreateTextPosition(
root, 5 , ax::mojom::TextAffinity::kUpstream);
ASSERT_FALSE(middle_root_upstream->IsNullPosition());
TestPositionType after_root = CreateTextPosition(
root, 10 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_root->IsNullPosition());
TestPositionType before_inline_box_1 = CreateTextPosition(
inline_box_1, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_1->IsNullPosition());
TestPositionType after_inline_box_1 = CreateTextPosition(
inline_box_1, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_inline_box_1->IsNullPosition());
TestPositionType before_inline_box_empty =
CreateTextPosition(inline_box_empty, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_empty->IsNullPosition());
TestPositionType before_inline_box_empty_tree = CreateTreePosition(
inline_box_empty, AXNodePosition::BEFORE_TEXT );
ASSERT_FALSE(before_inline_box_empty_tree->IsNullPosition());
TestPositionType after_inline_box_empty_tree =
CreateTreePosition(inline_box_empty, 0 );
ASSERT_FALSE(after_inline_box_empty_tree->IsNullPosition());
TestPositionType before_button_empty = CreateTextPosition(
button_empty, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_button_empty->IsNullPosition());
TestPositionType before_button_empty_tree = CreateTreePosition(
button_empty, AXNodePosition::BEFORE_TEXT );
ASSERT_FALSE(before_button_empty_tree->IsNullPosition());
TestPositionType after_button_empty_tree =
CreateTreePosition(button_empty, 0 );
ASSERT_FALSE(after_button_empty_tree->IsNullPosition());
TestPositionType before_inline_box_2 = CreateTextPosition(
inline_box_2, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_2->IsNullPosition());
TestPositionType after_inline_box_2 = CreateTextPosition(
inline_box_2, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_inline_box_2->IsNullPosition());
TestPositionType parent_position =
before_inline_box_1->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(link.id, parent_position->anchor_id());
EXPECT_EQ(0, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
TestPositionType leaf_position = before_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_1.id, leaf_position->anchor_id());
EXPECT_EQ(0, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
after_inline_box_1->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(link.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
leaf_position = middle_root_upstream->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_1.id, leaf_position->anchor_id());
EXPECT_EQ(5, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
before_inline_box_empty->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position = before_inline_box_empty_tree->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(1, parent_position->child_index());
parent_position = after_inline_box_empty_tree->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(2, parent_position->child_index());
parent_position = before_button_empty->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position = before_button_empty_tree->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(2, parent_position->child_index());
parent_position = after_button_empty_tree->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(3, parent_position->child_index());
parent_position =
before_inline_box_2->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(5, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
leaf_position = middle_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_empty.id, leaf_position->anchor_id());
EXPECT_EQ(0, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
after_inline_box_2->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(10, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
leaf_position = after_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_2.id, leaf_position->anchor_id());
EXPECT_EQ(5, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
}
TEST_F(AXPositionTest, CreateParentAndLeafPositionWithEmbeddedObjects) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root;
AXNodeData paragraph;
AXNodeData static_text_1;
AXNodeData inline_box_1;
AXNodeData static_text_2;
AXNodeData inline_box_2;
AXNodeData button_empty;
root.id = 1;
paragraph.id = 2;
static_text_1.id = 3;
inline_box_1.id = 4;
static_text_2.id = 5;
inline_box_2.id = 6;
button_empty.id = 7;
root.role = ax::mojom::Role::kRootWebArea;
root.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
root.child_ids = {paragraph.id, static_text_2.id, button_empty.id};
paragraph.role = ax::mojom::Role::kParagraph;
paragraph.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph.child_ids = {static_text_1.id};
static_text_1.role = ax::mojom::Role::kStaticText;
static_text_1.SetName("Paragraph");
static_text_1.child_ids = {inline_box_1.id};
inline_box_1.role = ax::mojom::Role::kInlineTextBox;
inline_box_1.SetName("Paragraph");
static_text_2.role = ax::mojom::Role::kStaticText;
static_text_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_2.SetName("Hello");
static_text_2.child_ids = {inline_box_2.id};
inline_box_2.role = ax::mojom::Role::kInlineTextBox;
inline_box_2.SetName("Hello");
button_empty.role = ax::mojom::Role::kButton;
button_empty.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
SetTree(CreateAXTree({root, paragraph, static_text_1, inline_box_1,
static_text_2, inline_box_2, button_empty}));
TestPositionType before_root = CreateTextPosition(
root, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_root->IsNullPosition());
TestPositionType middle_root = CreateTextPosition(
root, AXNode::kEmbeddedObjectCharacterLengthUTF16 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(middle_root->IsNullPosition());
TestPositionType middle_root_upstream = CreateTextPosition(
root, AXNode::kEmbeddedObjectCharacterLengthUTF16 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_FALSE(middle_root_upstream->IsNullPosition());
TestPositionType after_root = CreateTextPosition(
root, 7 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_root->IsNullPosition());
TestPositionType before_inline_box_1 = CreateTextPosition(
inline_box_1, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_1->IsNullPosition());
TestPositionType after_inline_box_1 = CreateTextPosition(
inline_box_1, 9 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_inline_box_1->IsNullPosition());
TestPositionType after_inline_box_1_tree =
CreateTreePosition(inline_box_1, 0 );
ASSERT_FALSE(after_inline_box_1_tree->IsNullPosition());
TestPositionType before_inline_box_2 = CreateTextPosition(
inline_box_2, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_inline_box_2->IsNullPosition());
TestPositionType after_inline_box_2 = CreateTextPosition(
inline_box_2, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(after_inline_box_2->IsNullPosition());
TestPositionType before_inline_box_2_tree = CreateTreePosition(
inline_box_2, AXNodePosition::BEFORE_TEXT );
ASSERT_FALSE(before_inline_box_2_tree->IsNullPosition());
TestPositionType after_inline_box_2_tree =
CreateTreePosition(inline_box_2, 0 );
ASSERT_FALSE(after_inline_box_2_tree->IsNullPosition());
TestPositionType before_button_empty = CreateTextPosition(
button_empty, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_FALSE(before_button_empty->IsNullPosition());
TestPositionType before_button_empty_tree = CreateTreePosition(
button_empty, AXNodePosition::BEFORE_TEXT );
ASSERT_FALSE(before_button_empty_tree->IsNullPosition());
TestPositionType after_button_empty_tree =
CreateTreePosition(button_empty, 0 );
ASSERT_FALSE(after_button_empty_tree->IsNullPosition());
TestPositionType parent_position = before_inline_box_1->CreateParentPosition()
->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(0, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
TestPositionType leaf_position = before_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_1.id, leaf_position->anchor_id());
EXPECT_EQ(0, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position = after_inline_box_1->CreateParentPosition()
->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterLengthUTF16,
parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position = after_inline_box_1_tree->CreateParentPosition()
->CreateParentPosition()
->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(1, parent_position->child_index());
leaf_position = middle_root_upstream->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_1.id, leaf_position->anchor_id());
EXPECT_EQ(9, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
before_inline_box_2->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterLengthUTF16,
parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
leaf_position = middle_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(inline_box_2.id, leaf_position->anchor_id());
EXPECT_EQ(0, leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
parent_position =
after_inline_box_2->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(6, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, parent_position->affinity());
parent_position =
before_inline_box_2_tree->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(1, parent_position->child_index());
parent_position =
after_inline_box_2_tree->CreateParentPosition()->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(2, parent_position->child_index());
parent_position = before_button_empty->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTextPosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(6, parent_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, parent_position->affinity());
parent_position = before_button_empty_tree->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(2, parent_position->child_index());
parent_position = after_button_empty_tree->CreateParentPosition();
ASSERT_NE(nullptr, parent_position);
EXPECT_TRUE(parent_position->IsTreePosition());
EXPECT_EQ(root.id, parent_position->anchor_id());
EXPECT_EQ(3, parent_position->child_index());
leaf_position = after_root->AsLeafTextPosition();
ASSERT_NE(nullptr, leaf_position);
EXPECT_TRUE(leaf_position->IsTextPosition());
EXPECT_EQ(button_empty.id, leaf_position->anchor_id());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterLengthUTF16,
leaf_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, leaf_position->affinity());
}
TEST_F(AXPositionTest, CreateNextAndPreviousLeafTextPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreateNextLeafTextPosition) {
TestPositionType check_box_position =
CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, check_box_position);
TestPositionType test_position =
check_box_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
TestPositionType root_position = CreateTextPosition(
root_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, root_position);
ASSERT_TRUE(root_position->IsTextPosition());
test_position = root_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
TestPositionType button_position = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, button_position);
ASSERT_TRUE(button_position->IsTextPosition());
test_position = button_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
TestPositionType text_field_position =
CreateTreePosition(root_, 2 );
ASSERT_NE(nullptr, text_field_position);
test_position = text_field_position->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
TestPositionType root_position2 = CreateTextPosition(
root_, 10 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, root_position2);
ASSERT_TRUE(root_position2->IsTextPosition());
test_position = root_position2->CreateNextLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
}
TEST_F(AXPositionTest, CreatePreviousLeafTextPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box2_, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
TestPositionType before_text_position =
CreateTreePosition(inline_box2_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, before_text_position);
test_position = before_text_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = test_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
TestPositionType text_field_position =
CreateTreePosition(text_field_, 2 );
ASSERT_NE(nullptr, text_field_position);
test_position = text_field_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
TestPositionType check_box_position = CreateTextPosition(
check_box_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, check_box_position);
ASSERT_TRUE(check_box_position->IsTextPosition());
test_position = check_box_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
TestPositionType root_position2 = CreateTextPosition(
root_, 10 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, root_position2);
ASSERT_TRUE(root_position2->IsTextPosition());
test_position = root_position2->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), test_position->tree_id());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
}
TEST_F(AXPositionTest, CreateNextLeafTreePosition) {
TestPositionType root_position =
CreateTreePosition(root_, 0 );
ASSERT_TRUE(root_position->IsTreePosition());
TestPositionType button_position =
CreateTreePosition(button_, AXNodePosition::BEFORE_TEXT);
TestPositionType checkbox_position =
CreateTreePosition(check_box_, AXNodePosition::BEFORE_TEXT);
TestPositionType inline_box1_position =
CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
TestPositionType line_break_position =
CreateTreePosition(line_break_, AXNodePosition::BEFORE_TEXT);
TestPositionType inline_box2_position =
CreateTreePosition(inline_box2_, AXNodePosition::BEFORE_TEXT);
TestPositionType test_position = root_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *button_position);
test_position = test_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *checkbox_position);
test_position = test_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *inline_box1_position);
test_position = test_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *line_break_position);
test_position = test_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *inline_box2_position);
test_position = test_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsNullPosition());
TestPositionType root_text_position = CreateTextPosition(
root_, 2 , ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(root_text_position->IsTextPosition());
test_position = root_text_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *inline_box1_position);
TestPositionType inline_box1_text_position = CreateTextPosition(
inline_box1_, 2 , ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(inline_box1_text_position->IsTextPosition());
test_position = inline_box1_text_position->CreateNextLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *line_break_position);
}
TEST_F(AXPositionTest, CreatePreviousLeafTreePosition) {
TestPositionType inline_box2_position =
CreateTreePosition(inline_box2_, AXNodePosition::BEFORE_TEXT);
ASSERT_TRUE(inline_box2_position->IsTreePosition());
TestPositionType line_break_position =
CreateTreePosition(line_break_, AXNodePosition::BEFORE_TEXT);
TestPositionType inline_box1_position =
CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
TestPositionType checkbox_position =
CreateTreePosition(check_box_, AXNodePosition::BEFORE_TEXT);
TestPositionType button_position =
CreateTreePosition(button_, AXNodePosition::BEFORE_TEXT);
TestPositionType test_position =
inline_box2_position->CreatePreviousLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *line_break_position);
test_position = test_position->CreatePreviousLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *inline_box1_position);
test_position = test_position->CreatePreviousLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *checkbox_position);
test_position = test_position->CreatePreviousLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *button_position);
test_position = test_position->CreatePreviousLeafTreePosition();
EXPECT_TRUE(test_position->IsNullPosition());
TestPositionType inline_box2_text_position = CreateTextPosition(
inline_box2_, 2 , ax::mojom::TextAffinity::kDownstream);
EXPECT_TRUE(inline_box2_text_position->IsTextPosition());
test_position = inline_box2_text_position->CreatePreviousLeafTreePosition();
EXPECT_TRUE(test_position->IsTreePosition());
EXPECT_EQ(*test_position, *line_break_position);
}
TEST_F(AXPositionTest,
AsLeafTextPositionBeforeAndAfterCharacterWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
ASSERT_TRUE(null_position->IsNullPosition());
TestPositionType test_position =
null_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest,
DISABLED_AsLeafTextPositionBeforeAndAfterCharacterWithInvalidPosition) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_data;
text_data.id = 2;
text_data.role = ax::mojom::Role::kStaticText;
text_data.SetName("some text");
root_data.child_ids = {text_data.id};
SetTree(CreateAXTree({root_data, text_data}));
TestPositionType text_position = CreateTextPosition(
text_data, 9 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->IsValid());
EXPECT_EQ(9, text_position->text_offset());
text_data.SetName("some tex");
AXTreeUpdate shorten_text_update;
shorten_text_update.nodes = {text_data};
ASSERT_TRUE(GetTree()->Unserialize(shorten_text_update));
EXPECT_FALSE(text_position->IsValid());
TestPositionType text_position_before =
text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_TRUE(text_position_before->IsNullPosition());
TestPositionType text_position_after =
text_position->AsLeafTextPositionAfterCharacter();
EXPECT_TRUE(text_position_after->IsNullPosition());
}
TEST_F(AXPositionTest,
AsLeafTextPositionBeforeAndAfterCharacterAtInvalidGraphemeBoundary) {
std::vector<int> text_offsets;
SetTree(CreateMultilingualDocument(&text_offsets));
TestPositionType test_position =
CreateTextPosition(*GetTree()->root(), 4 ,
ax::mojom::TextAffinity::kDownstream);
test_position = test_position->AsLeafTextPositionAfterCharacter();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->children()[1]->id(), test_position->anchor_id());
EXPECT_EQ(2, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 10 ,
ax::mojom::TextAffinity::kDownstream);
test_position = test_position->AsLeafTextPositionBeforeCharacter();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->children()[2]->id(), test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 10 ,
ax::mojom::TextAffinity::kUpstream);
test_position = test_position->AsLeafTextPositionBeforeCharacter();
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->children()[2]->id(), test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, AsLeafTextPositionBeforeCharacterNoAdjustment) {
TestPositionType text_position = CreateTextPosition(
root_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
text_position = CreateTextPosition(static_text1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
}
TEST_F(AXPositionTest, AsLeafTextPositionAfterCharacterNoAdjustment) {
TestPositionType text_position = CreateTextPosition(
root_, 13 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(root_, 7 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
}
TEST_F(AXPositionTest, AsLeafTextPositionBeforeCharacter) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 3 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
text_position = CreateTextPosition(root_, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest,
AsLeafTextPositionBeforeCharacterIncludingGeneratedNewlines) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType text_position = CreateTextPosition(
button_, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(root_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(root_, 2 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
text_position = CreateTextPosition(root_, 13 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionBeforeCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_FALSE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsLeafTextPositionAfterCharacter) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
text_position = CreateTextPosition(inline_box1_, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
text_position = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(root_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest,
AsLeafTextPositionAfterCharacterIncludingGeneratedNewlines) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType text_position = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
text_position = CreateTextPosition(button_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(check_box_.id, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->AsLeafTextPositionAfterCharacter();
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
}
TEST_F(AXPositionTest, CreateNextAndPreviousCharacterPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsValidPosition) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_data;
text_data.id = 2;
text_data.role = ax::mojom::Role::kStaticText;
text_data.SetName("some text");
root_data.child_ids = {text_data.id};
SetTree(CreateAXTree({root_data, text_data}));
TestPositionType text_position = CreateTextPosition(
text_data, 9 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->IsValid());
EXPECT_EQ(9, text_position->text_offset());
TestPositionType test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_TRUE(test_position->IsValid());
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_data.id, test_position->anchor_id());
EXPECT_EQ(9, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
EXPECT_TRUE(text_position->IsValid());
test_position = text_position->AsValidPosition();
EXPECT_TRUE(test_position->IsValid());
EXPECT_EQ(*test_position, *text_position);
text_data.SetName("some tex");
AXTreeUpdate shorten_text_update;
shorten_text_update.nodes = {text_data};
ASSERT_TRUE(GetTree()->Unserialize(shorten_text_update));
EXPECT_FALSE(text_position->IsValid());
text_position = text_position->AsValidPosition();
EXPECT_TRUE(text_position->IsValid());
EXPECT_EQ(8, text_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_TRUE(test_position->IsValid());
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_data.id, test_position->anchor_id());
EXPECT_EQ(8, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
EXPECT_TRUE(text_position->IsValid());
TestPositionType tree_position = text_position->AsTreePosition();
ASSERT_NE(nullptr, tree_position);
EXPECT_TRUE(tree_position->IsTreePosition());
EXPECT_TRUE(tree_position->IsValid());
EXPECT_EQ(0, tree_position->child_index());
AXTreeUpdate remove_node_update;
root_data.child_ids = {};
remove_node_update.nodes = {root_data};
ASSERT_TRUE(GetTree()->Unserialize(remove_node_update));
EXPECT_FALSE(text_position->IsValid());
EXPECT_FALSE(tree_position->IsValid());
text_position = text_position->AsValidPosition();
EXPECT_TRUE(text_position->IsValid());
tree_position = tree_position->AsValidPosition();
EXPECT_TRUE(tree_position->IsValid());
EXPECT_TRUE(text_position->IsNullPosition());
EXPECT_TRUE(tree_position->IsNullPosition());
}
TEST_F(AXPositionTest, AsValidPositionInDescendantOfEmptyObject) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData button_2;
AXNodeData static_text_3;
AXNodeData inline_box_4;
root_1.id = 1;
button_2.id = 2;
static_text_3.id = 3;
inline_box_4.id = 4;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {button_2.id};
button_2.role = ax::mojom::Role::kButton;
button_2.child_ids = {static_text_3.id};
static_text_3.role = ax::mojom::Role::kStaticText;
static_text_3.SetName("3.14");
static_text_3.child_ids = {inline_box_4.id};
inline_box_4.role = ax::mojom::Role::kInlineTextBox;
inline_box_4.SetName("3.14");
SetTree(CreateAXTree({root_1, button_2, static_text_3, inline_box_4}));
TestPositionType text_position =
CreateTextPosition(inline_box_4, 3, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_TRUE(text_position->IsValid());
EXPECT_EQ(*text_position, *text_position->AsValidPosition());
TestPositionType tree_position = CreateTreePosition(inline_box_4, 0);
AXNode& inline_box_4_node = *GetNode(inline_box_4.id);
ASSERT_TRUE(AXNodePosition::IsLeafNodeForTreePosition(inline_box_4_node));
EXPECT_EQ(tree_position->GetAnchor()->GetChildCount(), 0U);
EXPECT_EQ(tree_position->GetAnchor()->id(), inline_box_4.id);
EXPECT_TRUE(tree_position->IsLeaf());
ASSERT_NE(nullptr, tree_position);
EXPECT_TRUE(tree_position->IsTreePosition());
EXPECT_TRUE(tree_position->IsValid());
EXPECT_EQ(*tree_position, *tree_position->AsValidPosition());
static_text_3.AddState(ax::mojom::State::kIgnored);
inline_box_4.AddState(ax::mojom::State::kIgnored);
AXTreeUpdate update;
update.nodes = {static_text_3, inline_box_4};
ASSERT_TRUE(GetTree()->Unserialize(update));
EXPECT_TRUE(text_position->IsValid());
text_position = text_position->AsValidPosition();
EXPECT_TRUE(text_position->IsValid());
EXPECT_EQ(1, text_position->text_offset());
EXPECT_TRUE(tree_position->IsValid());
ASSERT_TRUE(tree_position->IsLeafTreePosition());
TestPositionType valid_tree_position = tree_position->AsValidPosition();
EXPECT_TRUE(valid_tree_position->IsValid());
EXPECT_NE(tree_position->GetAnchor(), valid_tree_position->GetAnchor());
EXPECT_TRUE(valid_tree_position->IsLeaf());
EXPECT_EQ(valid_tree_position->GetAnchor()->GetChildCount(), 1U);
EXPECT_EQ(valid_tree_position->GetAnchor()->id(), button_2.id);
EXPECT_EQ(1, valid_tree_position->child_index());
}
TEST_F(AXPositionTest, CreateNextCharacterPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box1_, 4 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(4, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(text_field_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
text_position = CreateTextPosition(text_field_, 12 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(13, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreateNextCharacterPositionIncludingGeneratedNewlines) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType text_position = CreateTextPosition(
inline_box1_, 6 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(6, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
}
TEST_F(AXPositionTest, CreatePreviousCharacterPosition) {
TestPositionType text_position = CreateTextPosition(
inline_box2_, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(4, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(4, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(4, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(text_field_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest,
CreatePreviousCharacterPositionIncludingGeneratedNewlines) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
TestPositionType text_position = CreateTextPosition(
inline_box2_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType test_position =
text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
text_position = CreateTextPosition(inline_box1_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(check_box_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(1, test_position->text_offset());
text_position = CreateTextPosition(button_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
test_position = text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(button_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
}
TEST_F(AXPositionTest, CreateNextCharacterPositionAtGraphemeBoundary) {
std::vector<int> text_offsets;
SetTree(CreateMultilingualDocument(&text_offsets));
TestPositionType test_position =
CreateTextPosition(*GetTree()->root(), 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, test_position);
ASSERT_TRUE(test_position->IsTextPosition());
for (auto iter = (text_offsets.begin() + 1); iter != text_offsets.end();
++iter) {
const int text_offset = *iter;
test_position = test_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
::testing::Message message;
message << "Expecting character boundary at " << text_offset << " in\n"
<< *test_position;
SCOPED_TRACE(message);
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(text_offset, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
test_position = CreateTextPosition(*GetTree()->root(), 3 ,
ax::mojom::TextAffinity::kDownstream);
test_position = test_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 4 ,
ax::mojom::TextAffinity::kDownstream);
test_position = test_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 9 ,
ax::mojom::TextAffinity::kUpstream);
test_position = test_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(9, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 10 ,
ax::mojom::TextAffinity::kUpstream);
test_position = test_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(12, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, CreatePreviousCharacterPositionAtGraphemeBoundary) {
std::vector<int> text_offsets;
SetTree(CreateMultilingualDocument(&text_offsets));
TestPositionType test_position = CreateTextPosition(
*GetTree()->root(), text_offsets.back() ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, test_position);
ASSERT_TRUE(test_position->IsTextPosition());
for (auto iter = (text_offsets.rbegin() + 1); iter != text_offsets.rend();
++iter) {
const int text_offset = *iter;
test_position = test_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
::testing::Message message;
message << "Expecting character boundary at " << text_offset << " in\n"
<< *test_position;
SCOPED_TRACE(message);
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(text_offset, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
test_position = CreateTextPosition(*GetTree()->root(), 3 ,
ax::mojom::TextAffinity::kDownstream);
test_position = test_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 4 ,
ax::mojom::TextAffinity::kDownstream);
test_position = test_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(3, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 9 ,
ax::mojom::TextAffinity::kUpstream);
test_position = test_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(9, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, test_position->affinity());
test_position = CreateTextPosition(*GetTree()->root(), 10 ,
ax::mojom::TextAffinity::kUpstream);
test_position = test_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(GetTree()->root()->id(), test_position->anchor_id());
EXPECT_EQ(9, test_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity());
}
TEST_F(AXPositionTest, ReciprocalCreateNextAndPreviousCharacterPosition) {
TestPositionType tree_position =
CreateTreePosition(root_, 0 );
TestPositionType text_position = tree_position->AsTextPosition();
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
size_t next_character_moves = 0;
while (!text_position->IsNullPosition()) {
TestPositionType moved_position =
text_position->CreateNextCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, moved_position);
text_position = std::move(moved_position);
++next_character_moves;
}
tree_position =
CreateTreePosition(root_, root_.child_ids.size() );
text_position = tree_position->AsTextPosition();
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
size_t previous_character_moves = 0;
while (!text_position->IsNullPosition()) {
TestPositionType moved_position =
text_position->CreatePreviousCharacterPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, moved_position);
text_position = std::move(moved_position);
++previous_character_moves;
}
EXPECT_EQ(next_character_moves, previous_character_moves);
EXPECT_EQ(strlen(TEXT_VALUE), next_character_moves - 1);
}
TEST_F(AXPositionTest, CreateNextAndPreviousWordStartPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, CreateNextAndPreviousWordEndPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
TestPositionType test_position = null_position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
test_position = null_position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
TEST_F(AXPositionTest, OperatorEquals) {
TestPositionType null_position1 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position1);
TestPositionType null_position2 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position2);
EXPECT_EQ(*null_position1, *null_position2);
TestPositionType button_position1 =
CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, button_position1);
TestPositionType button_position2 =
CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, button_position2);
EXPECT_EQ(*button_position1, *button_position2);
ASSERT_EQ(*AXNodePosition::CreateNullPosition(),
*AXNodePosition::CreateNullPosition());
TestPositionType tree_position1 =
CreateTreePosition(root_, 3 );
ASSERT_NE(nullptr, tree_position1);
TestPositionType tree_position2 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, tree_position2);
EXPECT_NE(*tree_position1, *tree_position2);
tree_position1 = CreateTreePosition(text_field_, 3 );
ASSERT_NE(nullptr, tree_position1);
tree_position2 = CreateTreePosition(text_field_, 3 );
ASSERT_NE(nullptr, tree_position2);
EXPECT_EQ(*tree_position1, *tree_position2);
tree_position1 =
CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, tree_position1);
tree_position2 =
CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, tree_position2);
EXPECT_EQ(*tree_position1, *tree_position2);
TestPositionType text_position1 = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
TestPositionType text_position2 = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_EQ(*text_position1, *text_position2);
text_position2 = CreateTextPosition(inline_box1_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
text_position1 = CreateTextPosition(inline_box1_, 5 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
EXPECT_NE(*text_position1, *text_position2);
text_position1 = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
text_position2 = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_EQ(*text_position1, *text_position2);
text_position1 = CreateTextPosition(static_text1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
text_position2 = CreateTextPosition(inline_box1_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_EQ(*text_position1, *text_position2);
text_position1 = CreateTextPosition(static_text2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
text_position2 = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_TRUE(
text_position1->AsLeafTextPositionBeforeCharacter()->IsNullPosition());
EXPECT_TRUE(
text_position2->AsLeafTextPositionBeforeCharacter()->IsNullPosition());
EXPECT_EQ(*text_position1, *text_position2);
}
TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetSameAnchorId) {
TestPositionType text_position_one = CreateTextPosition(
root_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position_one);
ASSERT_TRUE(text_position_one->IsTextPosition());
TestPositionType text_position_two = CreateTextPosition(
root_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position_two);
ASSERT_TRUE(text_position_two->IsTextPosition());
ASSERT_TRUE(*text_position_one == *text_position_two);
ASSERT_TRUE(*text_position_two == *text_position_one);
}
TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetDifferentAnchorIdRoot) {
TestPositionType text_position_one = CreateTextPosition(
root_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position_one);
ASSERT_TRUE(text_position_one->IsTextPosition());
TestPositionType text_position_two = CreateTextPosition(
check_box_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position_two);
ASSERT_TRUE(text_position_two->IsTextPosition());
EXPECT_TRUE(*text_position_one == *text_position_two);
EXPECT_TRUE(*text_position_two == *text_position_one);
}
TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetDifferentAnchorIdLeaf) {
TestPositionType text_position_one = CreateTextPosition(
button_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position_one);
ASSERT_TRUE(text_position_one->IsTextPosition());
TestPositionType text_position_two = CreateTextPosition(
check_box_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position_two);
ASSERT_TRUE(text_position_two->IsTextPosition());
ASSERT_TRUE(*text_position_one == *text_position_two);
ASSERT_TRUE(*text_position_two == *text_position_one);
}
TEST_F(AXPositionTest, OperatorEqualsTextPositionsInTextField) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData text_field_2;
AXNodeData generic_container_3;
AXNodeData static_text_4;
AXNodeData inline_box_5;
root_1.id = 1;
text_field_2.id = 2;
generic_container_3.id = 3;
static_text_4.id = 4;
inline_box_5.id = 5;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {text_field_2.id};
text_field_2.role = ax::mojom::Role::kTextField;
text_field_2.AddState(ax::mojom::State::kEditable);
text_field_2.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
"input");
text_field_2.child_ids = {generic_container_3.id};
generic_container_3.role = ax::mojom::Role::kGenericContainer;
generic_container_3.AddState(ax::mojom::State::kEditable);
generic_container_3.child_ids = {static_text_4.id};
static_text_4.role = ax::mojom::Role::kStaticText;
static_text_4.SetName("Hello");
static_text_4.child_ids = {inline_box_5.id};
inline_box_5.role = ax::mojom::Role::kInlineTextBox;
inline_box_5.SetName("Hello");
SetTree(CreateAXTree({root_1, text_field_2, generic_container_3,
static_text_4, inline_box_5}));
TestPositionType inline_text_position = CreateTextPosition(
inline_box_5, 4 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, inline_text_position);
TestPositionType text_field_position = CreateTextPosition(
text_field_2, 4 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_field_position);
EXPECT_EQ(*inline_text_position, *text_field_position);
EXPECT_EQ(*text_field_position, *inline_text_position);
}
TEST_F(AXPositionTest, OperatorEqualsTextPositionsInSearchBox) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData search_box_2;
AXNodeData generic_container_3;
AXNodeData generic_container_4;
AXNodeData static_text_5;
AXNodeData inline_box_6;
AXNodeData button_7;
AXNodeData static_text_8;
AXNodeData inline_box_9;
root_1.id = 1;
search_box_2.id = 2;
generic_container_3.id = 3;
generic_container_4.id = 4;
static_text_5.id = 5;
inline_box_6.id = 6;
button_7.id = 7;
static_text_8.id = 8;
inline_box_9.id = 9;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {search_box_2.id, button_7.id};
search_box_2.role = ax::mojom::Role::kSearchBox;
search_box_2.AddState(ax::mojom::State::kEditable);
search_box_2.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
"input");
search_box_2.child_ids = {generic_container_3.id};
generic_container_3.role = ax::mojom::Role::kGenericContainer;
generic_container_3.child_ids = {generic_container_4.id};
generic_container_4.role = ax::mojom::Role::kGenericContainer;
generic_container_4.AddState(ax::mojom::State::kEditable);
generic_container_4.child_ids = {static_text_5.id};
static_text_5.role = ax::mojom::Role::kStaticText;
static_text_5.SetName("Hello");
static_text_5.child_ids = {inline_box_6.id};
inline_box_6.role = ax::mojom::Role::kInlineTextBox;
inline_box_6.SetName("Hello");
button_7.role = ax::mojom::Role::kButton;
button_7.child_ids = {static_text_8.id};
static_text_8.role = ax::mojom::Role::kStaticText;
static_text_8.SetName("X");
static_text_8.child_ids = {inline_box_9.id};
inline_box_9.role = ax::mojom::Role::kInlineTextBox;
inline_box_9.SetName("X");
SetTree(CreateAXTree({root_1, search_box_2, generic_container_3,
generic_container_4, static_text_5, inline_box_6,
button_7, static_text_8, inline_box_9}));
TestPositionType inline_text_position = CreateTextPosition(
inline_box_6, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, inline_text_position);
TestPositionType search_box_position = CreateTextPosition(
search_box_2, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, search_box_position);
EXPECT_EQ(*search_box_position, *inline_text_position);
EXPECT_EQ(*inline_text_position, *search_box_position);
TestPositionType static_text_position = CreateTextPosition(
static_text_8, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, static_text_position);
TestPositionType button_position = CreateTextPosition(
button_7, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, button_position);
EXPECT_EQ(*button_position, *static_text_position);
EXPECT_EQ(*static_text_position, *button_position);
}
TEST_F(AXPositionTest, OperatorsTreePositionsAroundEmbeddedCharacter) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData paragraph_2;
AXNodeData link_3;
AXNodeData static_text_4;
AXNodeData inline_box_5;
AXNodeData paragraph_6;
AXNodeData static_text_7;
AXNodeData inline_box_8;
root_1.id = 1;
paragraph_2.id = 2;
link_3.id = 3;
static_text_4.id = 4;
inline_box_5.id = 5;
paragraph_6.id = 6;
static_text_7.id = 7;
inline_box_8.id = 8;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
root_1.child_ids = {paragraph_2.id, paragraph_6.id};
paragraph_2.role = ax::mojom::Role::kParagraph;
paragraph_2.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph_2.child_ids = {link_3.id};
link_3.role = ax::mojom::Role::kLink;
link_3.AddState(ax::mojom::State::kLinked);
link_3.child_ids = {static_text_4.id};
static_text_4.role = ax::mojom::Role::kStaticText;
static_text_4.SetName("Hello");
static_text_4.child_ids = {inline_box_5.id};
inline_box_5.role = ax::mojom::Role::kInlineTextBox;
inline_box_5.SetName("Hello");
paragraph_6.role = ax::mojom::Role::kParagraph;
paragraph_6.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph_6.child_ids = {static_text_7.id};
static_text_7.role = ax::mojom::Role::kStaticText;
static_text_7.SetName("World");
static_text_7.child_ids = {inline_box_8.id};
inline_box_8.role = ax::mojom::Role::kInlineTextBox;
inline_box_8.SetName("World");
SetTree(
CreateAXTree({root_1, paragraph_2, link_3, static_text_4, inline_box_5,
paragraph_6, static_text_7, inline_box_8}));
TestPositionType before_root_1 =
CreateTreePosition(root_1, 0 );
ASSERT_NE(nullptr, before_root_1);
TestPositionType middle_root_1 =
CreateTreePosition(root_1, 1 );
ASSERT_NE(nullptr, middle_root_1);
TestPositionType after_root_1 =
CreateTreePosition(root_1, 2 );
ASSERT_NE(nullptr, after_root_1);
TestPositionType before_paragraph_2 =
CreateTreePosition(paragraph_2, 0 );
ASSERT_NE(nullptr, before_paragraph_2);
TestPositionType after_paragraph_2 =
CreateTreePosition(paragraph_2, 1 );
ASSERT_NE(nullptr, after_paragraph_2);
TestPositionType before_paragraph_6 =
CreateTreePosition(paragraph_6, 0 );
ASSERT_NE(nullptr, before_paragraph_6);
TestPositionType after_paragraph_6 =
CreateTreePosition(paragraph_6, 1 );
ASSERT_NE(nullptr, before_paragraph_6);
TestPositionType before_inline_box_5 = CreateTreePosition(
inline_box_5, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, before_inline_box_5);
TestPositionType after_inline_box_5 =
CreateTreePosition(inline_box_5, 0 );
ASSERT_NE(nullptr, after_inline_box_5);
TestPositionType before_inline_box_8 = CreateTreePosition(
inline_box_8, AXNodePosition::BEFORE_TEXT );
ASSERT_NE(nullptr, before_inline_box_8);
TestPositionType after_inline_box_8 =
CreateTreePosition(inline_box_8, 0 );
ASSERT_NE(nullptr, after_inline_box_8);
EXPECT_EQ(*before_root_1, *before_paragraph_2);
EXPECT_EQ(*before_paragraph_2, *before_root_1);
EXPECT_EQ(*before_root_1, *before_inline_box_5);
EXPECT_EQ(*before_inline_box_5, *before_root_1);
EXPECT_LT(*before_root_1, *middle_root_1);
EXPECT_GT(*before_paragraph_6, *before_inline_box_5);
EXPECT_LT(*before_paragraph_2, *before_inline_box_8);
EXPECT_EQ(*middle_root_1, *before_paragraph_6);
EXPECT_EQ(*before_paragraph_6, *middle_root_1);
EXPECT_EQ(*middle_root_1, *before_inline_box_8);
EXPECT_EQ(*before_inline_box_8, *middle_root_1);
EXPECT_EQ(*middle_root_1, *after_paragraph_2);
EXPECT_EQ(*after_paragraph_2, *middle_root_1);
EXPECT_EQ(*middle_root_1, *after_inline_box_5);
EXPECT_EQ(*after_inline_box_5, *middle_root_1);
EXPECT_EQ(*after_root_1, *after_paragraph_6);
EXPECT_EQ(*after_paragraph_6, *after_root_1);
EXPECT_EQ(*after_root_1, *after_inline_box_8);
EXPECT_EQ(*after_inline_box_8, *after_root_1);
}
TEST_F(AXPositionTest, OperatorsTextPositionsAroundEmbeddedCharacter) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData paragraph_2;
AXNodeData link_3;
AXNodeData static_text_4;
AXNodeData inline_box_5;
AXNodeData paragraph_6;
AXNodeData static_text_7;
AXNodeData inline_box_8;
root_1.id = 1;
paragraph_2.id = 2;
link_3.id = 3;
static_text_4.id = 4;
inline_box_5.id = 5;
paragraph_6.id = 6;
static_text_7.id = 7;
inline_box_8.id = 8;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
root_1.child_ids = {paragraph_2.id, paragraph_6.id};
paragraph_2.role = ax::mojom::Role::kParagraph;
paragraph_2.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph_2.child_ids = {link_3.id};
link_3.role = ax::mojom::Role::kLink;
link_3.AddState(ax::mojom::State::kLinked);
link_3.child_ids = {static_text_4.id};
static_text_4.role = ax::mojom::Role::kStaticText;
static_text_4.SetName("Hello");
static_text_4.child_ids = {inline_box_5.id};
inline_box_5.role = ax::mojom::Role::kInlineTextBox;
inline_box_5.SetName("Hello");
paragraph_6.role = ax::mojom::Role::kParagraph;
paragraph_6.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
paragraph_6.child_ids = {static_text_7.id};
static_text_7.role = ax::mojom::Role::kStaticText;
static_text_7.SetName("World");
static_text_7.child_ids = {inline_box_8.id};
inline_box_8.role = ax::mojom::Role::kInlineTextBox;
inline_box_8.SetName("World");
SetTree(
CreateAXTree({root_1, paragraph_2, link_3, static_text_4, inline_box_5,
paragraph_6, static_text_7, inline_box_8}));
TestPositionType before_root_1 = CreateTextPosition(
root_1, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_root_1);
TestPositionType middle_root_1 = CreateTextPosition(
root_1, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, middle_root_1);
TestPositionType middle_root_1_upstream = CreateTextPosition(
root_1, 1 , ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, middle_root_1_upstream);
TestPositionType after_root_1 = CreateTextPosition(
root_1, 2 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_root_1);
TestPositionType before_paragraph_2 = CreateTextPosition(
paragraph_2, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_paragraph_2);
TestPositionType after_paragraph_2 = CreateTextPosition(
paragraph_2, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_paragraph_2);
TestPositionType before_paragraph_6 = CreateTextPosition(
paragraph_6, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_paragraph_6);
TestPositionType after_paragraph_6 = CreateTextPosition(
paragraph_6, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_paragraph_6);
TestPositionType before_inline_box_5 = CreateTextPosition(
inline_box_5, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_inline_box_5);
TestPositionType middle_inline_box_5 = CreateTextPosition(
inline_box_5, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, middle_inline_box_5);
TestPositionType after_inline_box_5 = CreateTextPosition(
inline_box_5, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_inline_box_5);
TestPositionType before_inline_box_8 = CreateTextPosition(
inline_box_8, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, before_inline_box_8);
TestPositionType middle_inline_box_8 = CreateTextPosition(
inline_box_8, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, middle_inline_box_8);
TestPositionType after_inline_box_8 = CreateTextPosition(
inline_box_8, 5 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, after_inline_box_8);
EXPECT_EQ(*before_root_1, *before_paragraph_2);
EXPECT_EQ(*before_paragraph_2, *before_root_1);
EXPECT_EQ(*before_root_1, *before_inline_box_5);
EXPECT_EQ(*before_inline_box_5, *before_root_1);
EXPECT_LT(*before_root_1, *middle_root_1);
EXPECT_LT(*before_paragraph_2, *before_inline_box_8);
EXPECT_EQ(*middle_root_1, *before_paragraph_6);
EXPECT_EQ(*before_paragraph_6, *middle_root_1);
EXPECT_EQ(*middle_root_1, *before_inline_box_8);
EXPECT_EQ(*before_inline_box_8, *middle_root_1);
EXPECT_GT(*middle_root_1, *after_paragraph_2);
EXPECT_LT(*after_paragraph_2, *middle_root_1);
EXPECT_GT(*middle_root_1, *after_inline_box_5);
EXPECT_EQ(*after_root_1, *middle_inline_box_8);
EXPECT_EQ(*middle_inline_box_8, *after_root_1);
EXPECT_LT(*middle_root_1_upstream, *middle_root_1);
EXPECT_EQ(*middle_root_1_upstream, *after_paragraph_2);
EXPECT_EQ(*after_paragraph_2, *middle_root_1_upstream);
EXPECT_EQ(*middle_root_1_upstream, *after_inline_box_5);
EXPECT_EQ(*after_inline_box_5, *middle_root_1_upstream);
EXPECT_EQ(*middle_root_1_upstream, *middle_inline_box_5);
EXPECT_EQ(*middle_inline_box_5, *middle_root_1_upstream);
EXPECT_LT(*before_inline_box_5, *middle_root_1);
EXPECT_LT(*before_inline_box_5, *before_paragraph_6);
EXPECT_LT(*before_inline_box_5, *before_inline_box_8);
EXPECT_LT(*middle_inline_box_5, *middle_root_1);
EXPECT_LT(*middle_inline_box_5, *before_paragraph_6);
EXPECT_LT(*middle_inline_box_5, *before_inline_box_8);
EXPECT_LT(*after_inline_box_5, *middle_root_1);
EXPECT_LT(*after_inline_box_5, *before_paragraph_6);
EXPECT_LT(*after_inline_box_5, *before_inline_box_8);
EXPECT_EQ(*after_root_1, *after_paragraph_6);
EXPECT_EQ(*after_paragraph_6, *after_root_1);
EXPECT_EQ(*after_root_1, *after_inline_box_8);
EXPECT_EQ(*after_inline_box_8, *after_root_1);
root_1.AddState(ax::mojom::State::kIgnored);
root_1.RemoveBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject);
paragraph_2.AddState(ax::mojom::State::kIgnored);
paragraph_2.RemoveBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject);
inline_box_5.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box_8.id);
paragraph_6.AddState(ax::mojom::State::kIgnored);
paragraph_6.RemoveBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject);
inline_box_8.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box_5.id);
AXTreeUpdate update;
update.root_id = root_1.id;
update.nodes = {root_1, paragraph_2, inline_box_5, paragraph_6, inline_box_8};
ASSERT_TRUE(GetTree()->Unserialize(update));
EXPECT_EQ(*after_root_1, *middle_inline_box_8);
EXPECT_EQ(*middle_inline_box_8, *after_root_1);
EXPECT_LT(*before_inline_box_5, *middle_root_1);
EXPECT_LT(*before_inline_box_5, *before_paragraph_6);
EXPECT_LT(*before_inline_box_5, *before_inline_box_8);
EXPECT_EQ(*middle_inline_box_5, *middle_root_1);
EXPECT_LT(*middle_inline_box_5, *before_paragraph_6);
EXPECT_LT(*middle_inline_box_5, *before_inline_box_8);
EXPECT_EQ(*after_inline_box_5, *middle_root_1);
EXPECT_EQ(*after_inline_box_5, *before_paragraph_6);
EXPECT_EQ(*after_inline_box_5, *before_inline_box_8);
}
TEST_F(AXPositionTest, OperatorsLessThanAndGreaterThan) {
TestPositionType null_position1 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position1);
TestPositionType null_position2 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position2);
EXPECT_FALSE(*null_position1 < *null_position2);
EXPECT_FALSE(*null_position1 > *null_position2);
TestPositionType button_position1 =
CreateTreePosition(root_, 0 );
ASSERT_NE(nullptr, button_position1);
TestPositionType button_position2 =
CreateTreePosition(root_, 1 );
ASSERT_NE(nullptr, button_position2);
EXPECT_LT(*button_position1, *button_position2);
EXPECT_GT(*button_position2, *button_position1);
TestPositionType tree_position1 =
CreateTreePosition(text_field_, 2 );
ASSERT_NE(nullptr, tree_position1);
TestPositionType tree_position2 =
CreateTreePosition(text_field_, 3 );
ASSERT_NE(nullptr, tree_position2);
EXPECT_LT(*tree_position1, *tree_position2);
EXPECT_GT(*tree_position2, *tree_position1);
tree_position1 =
CreateTreePosition(inline_box1_, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, tree_position1);
tree_position2 = CreateTreePosition(inline_box1_, 0 );
ASSERT_NE(nullptr, tree_position2);
EXPECT_LT(*tree_position1, *tree_position2);
EXPECT_GT(*tree_position2, *tree_position1);
TestPositionType text_position1 = CreateTextPosition(
inline_box1_, 2 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
TestPositionType text_position2 = CreateTextPosition(
inline_box1_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
text_position2 = CreateTextPosition(inline_box1_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
text_position1 = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
text_position2 = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
text_position1 = CreateTextPosition(text_field_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
text_position2 = CreateTextPosition(inline_box1_, 5 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
text_position1 = CreateTextPosition(inline_box2_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
text_position2 = CreateTextPosition(line_break_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
text_position2 = CreateTextPosition(line_break_, 1 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
text_position1 = CreateTextPosition(inline_box2_, 6 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_TRUE(text_position1->IsTextPosition());
EXPECT_TRUE(
text_position1->AsLeafTextPositionBeforeCharacter()->IsNullPosition());
text_position2 = CreateTextPosition(static_text2_, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position2);
ASSERT_TRUE(text_position2->IsTextPosition());
EXPECT_GT(*text_position1, *text_position2);
EXPECT_LT(*text_position2, *text_position1);
}
TEST_F(AXPositionTest, Swap) {
TestPositionType null_position1 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position1);
TestPositionType null_position2 = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position2);
swap(*null_position1, *null_position2);
EXPECT_TRUE(null_position1->IsNullPosition());
EXPECT_TRUE(null_position2->IsNullPosition());
TestPositionType tree_position1 =
CreateTreePosition(root_, 2 );
ASSERT_NE(nullptr, tree_position1);
TestPositionType tree_position2 =
CreateTreePosition(text_field_, 3 );
ASSERT_NE(nullptr, tree_position2);
swap(*tree_position1, *tree_position2);
EXPECT_TRUE(tree_position1->IsTreePosition());
EXPECT_EQ(GetTreeID(), tree_position1->tree_id());
EXPECT_EQ(text_field_.id, tree_position1->anchor_id());
EXPECT_EQ(3, tree_position1->child_index());
EXPECT_TRUE(tree_position1->IsTreePosition());
EXPECT_EQ(GetTreeID(), tree_position2->tree_id());
EXPECT_EQ(root_.id, tree_position2->anchor_id());
EXPECT_EQ(2, tree_position2->child_index());
swap(*tree_position1, *null_position1);
EXPECT_TRUE(tree_position1->IsNullPosition());
EXPECT_TRUE(null_position1->IsTreePosition());
EXPECT_EQ(GetTreeID(), null_position1->tree_id());
EXPECT_EQ(text_field_.id, null_position1->anchor_id());
EXPECT_EQ(3, null_position1->child_index());
TestPositionType text_position = CreateTextPosition(
line_break_, 1 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
swap(*text_position, *null_position1);
EXPECT_TRUE(null_position1->IsTextPosition());
EXPECT_EQ(GetTreeID(), text_position->tree_id());
EXPECT_EQ(line_break_.id, null_position1->anchor_id());
EXPECT_EQ(1, null_position1->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, null_position1->affinity());
EXPECT_TRUE(text_position->IsTreePosition());
EXPECT_EQ(GetTreeID(), text_position->tree_id());
EXPECT_EQ(text_field_.id, text_position->anchor_id());
EXPECT_EQ(3, text_position->child_index());
}
TEST_F(AXPositionTest, CreateNextAnchorPosition) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData text_data;
text_data.id = 2;
text_data.role = ax::mojom::Role::kStaticText;
text_data.SetName("some text");
AXNodeData text_field_data;
text_field_data.id = 3;
text_field_data.role = ax::mojom::Role::kTextField;
text_field_data.AddState(ax::mojom::State::kEditable);
text_field_data.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
"input");
AXNodeData empty_text_data;
empty_text_data.id = 4;
empty_text_data.role = ax::mojom::Role::kStaticText;
empty_text_data.SetNameExplicitlyEmpty();
AXNodeData more_text_data;
more_text_data.id = 5;
more_text_data.role = ax::mojom::Role::kStaticText;
more_text_data.SetName("more text");
root_data.child_ids = {text_data.id, text_field_data.id, more_text_data.id};
text_field_data.child_ids = {empty_text_data.id};
SetTree(CreateAXTree({root_data, text_data, text_field_data, empty_text_data,
more_text_data}));
TestPositionType text_position1 = CreateTextPosition(
text_data, 8 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position1);
ASSERT_FALSE(text_position1->CreateNextAnchorPosition()
->CreateNextAnchorPosition()
->IsNullPosition());
}
TEST_F(AXPositionTest, CreateLinePositionsMultipleAnchorsInSingleLine) {
AXNodeData root;
AXNodeData inline_box1;
AXNodeData inline_box2;
AXNodeData inline_box3;
AXNodeData inline_block;
AXNodeData static_text1;
AXNodeData static_text2;
AXNodeData static_text3;
root.id = 1;
static_text1.id = 2;
inline_box1.id = 3;
inline_block.id = 4;
static_text2.id = 5;
inline_box2.id = 6;
static_text3.id = 7;
inline_box3.id = 8;
root.role = ax::mojom::Role::kRootWebArea;
root.child_ids = {static_text1.id, inline_block.id, static_text3.id};
static_text1.role = ax::mojom::Role::kStaticText;
static_text1.SetName("before");
static_text1.child_ids = {inline_box1.id};
inline_box1.role = ax::mojom::Role::kInlineTextBox;
inline_box1.SetName("before");
inline_box1.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box2.id);
inline_block.role = ax::mojom::Role::kGenericContainer;
inline_block.child_ids = {static_text2.id};
static_text2.role = ax::mojom::Role::kStaticText;
static_text2.SetName("inside");
static_text2.child_ids = {inline_box2.id};
inline_box2.role = ax::mojom::Role::kInlineTextBox;
inline_box2.SetName("inside");
inline_box2.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box1.id);
inline_box2.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId,
inline_box3.id);
static_text3.role = ax::mojom::Role::kStaticText;
static_text3.SetName("after");
static_text3.child_ids = {inline_box3.id};
inline_box3.role = ax::mojom::Role::kInlineTextBox;
inline_box3.SetName("after");
inline_box3.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId,
inline_box2.id);
SetTree(CreateAXTree({root, static_text1, inline_box1, inline_block,
static_text2, inline_box2, static_text3, inline_box3}));
TestPositionType text_position = CreateTextPosition(
inline_block, 3 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType next_line_start_position =
text_position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, next_line_start_position);
EXPECT_TRUE(next_line_start_position->IsTextPosition());
EXPECT_EQ(inline_box3.id, next_line_start_position->anchor_id());
EXPECT_EQ(5, next_line_start_position->text_offset());
TestPositionType previous_line_start_position =
text_position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, previous_line_start_position);
EXPECT_TRUE(previous_line_start_position->IsTextPosition());
EXPECT_EQ(inline_box1.id, previous_line_start_position->anchor_id());
EXPECT_EQ(0, previous_line_start_position->text_offset());
TestPositionType next_line_end_position =
text_position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, next_line_end_position);
EXPECT_TRUE(next_line_end_position->IsTextPosition());
EXPECT_EQ(inline_box3.id, next_line_end_position->anchor_id());
EXPECT_EQ(5, next_line_end_position->text_offset());
TestPositionType previous_line_end_position =
text_position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, previous_line_end_position);
EXPECT_TRUE(previous_line_end_position->IsTextPosition());
EXPECT_EQ(inline_box1.id, previous_line_end_position->anchor_id());
EXPECT_EQ(0, previous_line_end_position->text_offset());
}
TEST_F(AXPositionTest, CreateNextWordPositionInList) {
AXNodeData root;
AXNodeData list;
AXNodeData list_item1;
AXNodeData list_item2;
AXNodeData list_marker1;
AXNodeData list_marker2;
AXNodeData inline_box1;
AXNodeData inline_box2;
AXNodeData inline_box3;
AXNodeData inline_box4;
AXNodeData static_text1;
AXNodeData static_text2;
AXNodeData static_text3;
AXNodeData static_text4;
root.id = 1;
list.id = 2;
list_item1.id = 3;
list_marker1.id = 4;
static_text1.id = 5;
inline_box1.id = 6;
static_text2.id = 7;
inline_box2.id = 8;
list_item2.id = 9;
list_marker2.id = 10;
static_text3.id = 11;
inline_box3.id = 12;
static_text4.id = 13;
inline_box4.id = 14;
root.role = ax::mojom::Role::kRootWebArea;
root.child_ids = {list.id};
list.role = ax::mojom::Role::kList;
list.child_ids = {list_item1.id, list_item2.id};
list_item1.role = ax::mojom::Role::kListItem;
list_item1.child_ids = {list_marker1.id, static_text2.id};
list_item1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
list_marker1.role = ax::mojom::Role::kListMarker;
list_marker1.child_ids = {static_text1.id};
static_text1.role = ax::mojom::Role::kStaticText;
static_text1.SetName("1. ");
static_text1.child_ids = {inline_box1.id};
inline_box1.role = ax::mojom::Role::kInlineTextBox;
inline_box1.SetName("1. ");
inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0});
inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{3});
static_text2.role = ax::mojom::Role::kStaticText;
static_text2.SetName("first item");
static_text2.child_ids = {inline_box2.id};
inline_box2.role = ax::mojom::Role::kInlineTextBox;
inline_box2.SetName("first item");
inline_box2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0, 6});
inline_box2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{5});
list_item2.role = ax::mojom::Role::kListItem;
list_item2.child_ids = {list_marker2.id, static_text4.id};
list_item2.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
list_marker2.role = ax::mojom::Role::kListMarker;
list_marker2.child_ids = {static_text3.id};
static_text3.role = ax::mojom::Role::kStaticText;
static_text3.SetName("2. ");
static_text3.child_ids = {inline_box3.id};
inline_box3.role = ax::mojom::Role::kInlineTextBox;
inline_box3.SetName("2. ");
inline_box3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0});
inline_box3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{3});
static_text4.role = ax::mojom::Role::kStaticText;
static_text4.SetName("second item");
static_text4.child_ids = {inline_box4.id};
inline_box4.role = ax::mojom::Role::kInlineTextBox;
inline_box4.SetName("second item");
inline_box4.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0, 7});
inline_box4.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{6});
SetTree(CreateAXTree({root, list, list_item1, list_marker1, static_text1,
inline_box1, static_text2, inline_box2, list_item2,
list_marker2, static_text3, inline_box3, static_text4,
inline_box4}));
TestPositionType text_position = CreateTextPosition(
inline_box1, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box1.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box2.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box2.id, text_position->anchor_id());
ASSERT_EQ(6, text_position->text_offset());
text_position = text_position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box3.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box4.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box4.id, text_position->anchor_id());
ASSERT_EQ(7, text_position->text_offset());
}
TEST_F(AXPositionTest, CreatePreviousWordPositionInList) {
AXNodeData root;
AXNodeData list;
AXNodeData list_item1;
AXNodeData list_item2;
AXNodeData list_marker1;
AXNodeData list_marker2;
AXNodeData inline_box1;
AXNodeData inline_box2;
AXNodeData inline_box3;
AXNodeData inline_box4;
AXNodeData static_text1;
AXNodeData static_text2;
AXNodeData static_text3;
AXNodeData static_text4;
root.id = 1;
list.id = 2;
list_item1.id = 3;
list_marker1.id = 4;
static_text1.id = 5;
inline_box1.id = 6;
static_text2.id = 7;
inline_box2.id = 8;
list_item2.id = 9;
list_marker2.id = 10;
static_text3.id = 11;
inline_box3.id = 12;
static_text4.id = 13;
inline_box4.id = 14;
root.role = ax::mojom::Role::kRootWebArea;
root.child_ids = {list.id};
list.role = ax::mojom::Role::kList;
list.child_ids = {list_item1.id, list_item2.id};
list_item1.role = ax::mojom::Role::kListItem;
list_item1.child_ids = {list_marker1.id, static_text2.id};
list_item1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
list_marker1.role = ax::mojom::Role::kListMarker;
list_marker1.child_ids = {static_text1.id};
static_text1.role = ax::mojom::Role::kStaticText;
static_text1.SetName("1. ");
static_text1.child_ids = {inline_box1.id};
inline_box1.role = ax::mojom::Role::kInlineTextBox;
inline_box1.SetName("1. ");
inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0});
inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{3});
static_text2.role = ax::mojom::Role::kStaticText;
static_text2.SetName("first item");
static_text2.child_ids = {inline_box2.id};
inline_box2.role = ax::mojom::Role::kInlineTextBox;
inline_box2.SetName("first item");
inline_box2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0, 6});
inline_box2.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{5});
list_item2.role = ax::mojom::Role::kListItem;
list_item2.child_ids = {list_marker2.id, static_text4.id};
list_item2.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
list_marker2.role = ax::mojom::Role::kListMarker;
list_marker2.child_ids = {static_text3.id};
static_text3.role = ax::mojom::Role::kStaticText;
static_text3.SetName("2. ");
static_text3.child_ids = {inline_box3.id};
inline_box3.role = ax::mojom::Role::kInlineTextBox;
inline_box3.SetName("2. ");
inline_box3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0});
inline_box3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{3});
static_text4.role = ax::mojom::Role::kStaticText;
static_text4.SetName("second item");
static_text4.child_ids = {inline_box4.id};
inline_box4.role = ax::mojom::Role::kInlineTextBox;
inline_box4.SetName("second item");
inline_box4.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0, 7});
inline_box4.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{6});
SetTree(CreateAXTree({root, list, list_item1, list_marker1, static_text1,
inline_box1, static_text2, inline_box2, list_item2,
list_marker2, static_text3, inline_box3, static_text4,
inline_box4}));
TestPositionType text_position = CreateTextPosition(
inline_box4, 11 , ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box4.id, text_position->anchor_id());
ASSERT_EQ(11, text_position->text_offset());
text_position = text_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box4.id, text_position->anchor_id());
ASSERT_EQ(7, text_position->text_offset());
text_position = text_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box4.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box3.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box2.id, text_position->anchor_id());
ASSERT_EQ(6, text_position->text_offset());
text_position = text_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box2.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
text_position = text_position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(inline_box1.id, text_position->anchor_id());
ASSERT_EQ(0, text_position->text_offset());
}
TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData static_text_2;
AXNodeData inline_box_3;
AXNodeData text_field_4;
AXNodeData generic_container_5;
AXNodeData static_text_6;
AXNodeData inline_box_7;
AXNodeData heading_8;
AXNodeData static_text_9;
AXNodeData inline_box_10;
AXNodeData generic_container_11;
AXNodeData generic_container_12;
AXNodeData static_text_13;
AXNodeData button_14;
AXNodeData generic_container_15;
AXNodeData generic_container_16;
root_1.id = 1;
static_text_2.id = 2;
inline_box_3.id = 3;
text_field_4.id = 4;
generic_container_5.id = 5;
static_text_6.id = 6;
inline_box_7.id = 7;
heading_8.id = 8;
static_text_9.id = 9;
inline_box_10.id = 10;
generic_container_11.id = 11;
generic_container_12.id = 12;
static_text_13.id = 13;
button_14.id = 14;
generic_container_15.id = 15;
generic_container_16.id = 16;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.child_ids = {static_text_2.id, text_field_4.id,
static_text_6.id, heading_8.id,
generic_container_11.id, generic_container_12.id,
static_text_13.id, button_14.id};
static_text_2.role = ax::mojom::Role::kStaticText;
static_text_2.SetName("Hello ");
static_text_2.child_ids = {inline_box_3.id};
inline_box_3.role = ax::mojom::Role::kInlineTextBox;
inline_box_3.SetName("Hello ");
inline_box_3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0});
inline_box_3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{6});
text_field_4.role = ax::mojom::Role::kTextField;
text_field_4.child_ids = {generic_container_5.id};
generic_container_5.role = ax::mojom::Role::kGenericContainer;
generic_container_5.AddState(ax::mojom::State::kIgnored);
static_text_6.role = ax::mojom::Role::kStaticText;
static_text_6.SetName(" world");
static_text_6.child_ids = {inline_box_7.id};
inline_box_7.role = ax::mojom::Role::kInlineTextBox;
inline_box_7.SetName(" world");
inline_box_7.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{1});
inline_box_7.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{6});
heading_8.role = ax::mojom::Role::kHeading;
heading_8.child_ids = {static_text_9.id};
static_text_9.role = ax::mojom::Role::kStaticText;
static_text_9.child_ids = {inline_box_10.id};
static_text_9.SetName("3.14");
inline_box_10.role = ax::mojom::Role::kInlineTextBox;
inline_box_10.SetName("3.14");
generic_container_11.role = ax::mojom::Role::kGenericContainer;
generic_container_11.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
generic_container_11.AddState(ax::mojom::State::kIgnored);
generic_container_12.role = ax::mojom::Role::kGenericContainer;
generic_container_12.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_13.role = ax::mojom::Role::kStaticText;
static_text_13.SetName("hey");
button_14.role = ax::mojom::Role::kButton;
button_14.child_ids = {generic_container_15.id, generic_container_16.id};
generic_container_15.role = ax::mojom::Role::kGenericContainer;
generic_container_15.AddState(ax::mojom::State::kIgnored);
generic_container_16.role = ax::mojom::Role::kGenericContainer;
generic_container_16.AddState(ax::mojom::State::kIgnored);
SetTree(CreateAXTree(
{root_1, static_text_2, inline_box_3, text_field_4, generic_container_5,
static_text_6, inline_box_7, heading_8, static_text_9, inline_box_10,
generic_container_11, generic_container_12, static_text_13, button_14,
generic_container_15, generic_container_16}));
TestPositionType position =
CreateTextPosition(inline_box_3, 0 ,
ax::mojom::TextAffinity::kDownstream);
TestPositionType result_position = position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(text_field_4.id, result_position->anchor_id());
EXPECT_EQ(0, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterUTF16, result_position->GetText());
position = std::move(result_position);
result_position = position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(inline_box_7.id, result_position->anchor_id());
EXPECT_EQ(1, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(u" world", result_position->GetText());
position = std::move(result_position);
result_position = position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(text_field_4.id, result_position->anchor_id());
EXPECT_EQ(0, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterUTF16, result_position->GetText());
position = std::move(result_position);
result_position = position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(inline_box_3.id, result_position->anchor_id());
EXPECT_EQ(0, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(u"Hello ", result_position->GetText());
position = std::move(result_position);
result_position = position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(inline_box_3.id, result_position->anchor_id());
EXPECT_EQ(6, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(u"Hello ", result_position->GetText());
position = std::move(result_position);
result_position = position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(text_field_4.id, result_position->anchor_id());
EXPECT_EQ(1, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterUTF16, result_position->GetText());
position = std::move(result_position);
result_position = position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(inline_box_7.id, result_position->anchor_id());
EXPECT_EQ(6, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(u" world", result_position->GetText());
position = std::move(result_position);
result_position = position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(text_field_4.id, result_position->anchor_id());
EXPECT_EQ(1, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterUTF16, result_position->GetText());
position = std::move(result_position);
result_position = position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
EXPECT_TRUE(result_position->IsTextPosition());
EXPECT_EQ(inline_box_3.id, result_position->anchor_id());
EXPECT_EQ(6, result_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity());
EXPECT_EQ(u"Hello ", result_position->GetText());
position = CreateTextPosition(generic_container_5, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_FALSE(position->IsNullPosition());
EXPECT_TRUE(position->GetText().empty());
position = CreateTextPosition(root_1, 0 ,
ax::mojom::TextAffinity::kDownstream);
std::u16string expected_text =
base::StrCat({u"Hello ", AXNode::kEmbeddedObjectCharacterUTF16, u" world",
AXNode::kEmbeddedObjectCharacterUTF16,
AXNode::kEmbeddedObjectCharacterUTF16, u"hey",
AXNode::kEmbeddedObjectCharacterUTF16});
EXPECT_EQ(expected_text, position->GetText());
position = CreateTextPosition(text_field_4, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_EQ(AXNode::kEmbeddedObjectCharacterLengthUTF16,
position->MaxTextOffset())
<< *position;
position = position->CreateParentPosition();
EXPECT_EQ(19, position->MaxTextOffset()) << *position;
position = CreateTextPosition(root_1, 0 ,
ax::mojom::TextAffinity::kDownstream);
EXPECT_EQ(19, position->MaxTextOffset()) << *position;
TestPositionType text_position =
CreateTextPosition(generic_container_12, 0 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
text_position = text_position->CreatePreviousFormatStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(generic_container_12.id, text_position->anchor_id());
EXPECT_EQ(0, text_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, text_position->affinity());
text_position = CreateTextPosition(static_text_13, 3 ,
ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
text_position = text_position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsLeafTextPosition());
EXPECT_EQ(button_14.id, text_position->anchor_id());
EXPECT_EQ(1, text_position->text_offset());
EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, text_position->affinity());
TestPositionType generic_container_position =
CreateTreePosition(generic_container_16, AXNodePosition::BEFORE_TEXT);
ASSERT_NE(nullptr, generic_container_position);
ASSERT_TRUE(generic_container_position->IsTreePosition());
EXPECT_EQ(generic_container_16.id, generic_container_position->anchor_id());
text_position = generic_container_position->CreatePreviousLeafTextPosition();
EXPECT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(GetTreeID(), text_position->tree_id());
EXPECT_EQ(button_14.id, text_position->anchor_id());
}
TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterEmbedObject) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXTreeID child_tree_id = AXTreeID::CreateNewAXTreeID();
AXNodeData root;
AXNodeData embed_object;
root.id = 1;
embed_object.id = 2;
root.role = ax::mojom::Role::kRootWebArea;
root.child_ids = {embed_object.id};
embed_object.role = ax::mojom::Role::kEmbeddedObject;
embed_object.AddChildTreeId(child_tree_id);
SetTree(CreateAXTree({root, embed_object}));
AXNodeData child_root;
child_root.id = 1;
child_root.role = ax::mojom::Role::kPdfRoot;
AXTreeUpdate update;
update.tree_data.tree_id = child_tree_id;
update.tree_data.parent_tree_id = GetTreeID();
update.has_tree_data = true;
update.root_id = child_root.id;
update.nodes.push_back(child_root);
TestSingleAXTreeManager child_tree_manager(std::make_unique<AXTree>(update));
TestPositionType tree_position =
CreateTreePosition(embed_object, 0 );
ASSERT_TRUE(tree_position->IsTreePosition());
EXPECT_FALSE(tree_position->IsLeaf());
}
TEST_F(AXPositionTest, TextNavigationWithCollapsedCombobox) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_1;
AXNodeData static_text_2;
AXNodeData inline_box_3;
AXNodeData popup_button_4;
AXNodeData menu_list_popup_5;
AXNodeData menu_list_option_6;
AXNodeData static_text_7;
AXNodeData inline_box_8;
root_1.id = 1;
static_text_2.id = 2;
inline_box_3.id = 3;
popup_button_4.id = 4;
menu_list_popup_5.id = 5;
menu_list_option_6.id = 6;
static_text_7.id = 7;
inline_box_8.id = 8;
root_1.role = ax::mojom::Role::kRootWebArea;
root_1.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
root_1.child_ids = {static_text_2.id, popup_button_4.id, static_text_7.id};
static_text_2.role = ax::mojom::Role::kStaticText;
static_text_2.SetName("Hi");
static_text_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_2.child_ids = {inline_box_3.id};
inline_box_3.role = ax::mojom::Role::kInlineTextBox;
inline_box_3.SetName("Hi");
inline_box_3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
{0});
inline_box_3.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, {2});
popup_button_4.role = ax::mojom::Role::kComboBoxSelect;
popup_button_4.child_ids = {menu_list_popup_5.id};
popup_button_4.AddState(ax::mojom::State::kCollapsed);
menu_list_popup_5.role = ax::mojom::Role::kMenuListPopup;
menu_list_popup_5.child_ids = {menu_list_option_6.id};
menu_list_option_6.role = ax::mojom::Role::kMenuListOption;
menu_list_option_6.SetName("Option");
menu_list_option_6.SetNameFrom(ax::mojom::NameFrom::kContents);
menu_list_option_6.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_7.role = ax::mojom::Role::kStaticText;
static_text_7.SetName("3.14");
static_text_7.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
static_text_7.child_ids = {inline_box_8.id};
inline_box_8.role = ax::mojom::Role::kInlineTextBox;
inline_box_8.SetName("3.14");
inline_box_8.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
{0});
inline_box_8.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, {4});
SetTree(CreateAXTree({root_1, static_text_2, inline_box_3, popup_button_4,
menu_list_popup_5, menu_list_option_6, static_text_7,
inline_box_8}));
TestPositionType position =
CreateTextPosition(inline_box_3, 0, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, position);
position = position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(popup_button_4.id, position->anchor_id());
EXPECT_EQ(0, position->text_offset());
position = position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(inline_box_8.id, position->anchor_id());
EXPECT_EQ(0, position->text_offset());
position =
CreateTextPosition(inline_box_8, 4, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, position);
position = position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(popup_button_4.id, position->anchor_id());
EXPECT_EQ(1, position->text_offset());
position = position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(inline_box_3.id, position->anchor_id());
EXPECT_EQ(2, position->text_offset());
popup_button_4.RemoveState(ax::mojom::State::kCollapsed);
popup_button_4.AddState(ax::mojom::State::kExpanded);
AXTreeUpdate update;
update.nodes = {popup_button_4};
ASSERT_TRUE(GetTree()->Unserialize(update));
position =
CreateTextPosition(inline_box_3, 0, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, position);
position = position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(menu_list_option_6.id, position->anchor_id());
EXPECT_EQ(0, position->text_offset());
position = position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(inline_box_8.id, position->anchor_id());
EXPECT_EQ(0, position->text_offset());
position =
CreateTextPosition(inline_box_8, 4, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, position);
position = position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(menu_list_option_6.id, position->anchor_id());
EXPECT_EQ(6, position->text_offset());
position = position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, position);
EXPECT_EQ(inline_box_3.id, position->anchor_id());
EXPECT_EQ(2, position->text_offset());
}
TEST_F(AXPositionTest, CreatePositionAtTextBoundaryWithHiddenLineBreak) {
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData editable_container;
editable_container.id = 12;
editable_container.role = ax::mojom::Role::kGenericContainer;
editable_container.AddState(ax::mojom::State::kEditable);
editable_container.AddState(ax::mojom::State::kFocusable);
editable_container.AddState(ax::mojom::State::kMultiline);
editable_container.AddState(ax::mojom::State::kRichlyEditable);
editable_container.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
AXNodeData first_div;
first_div.id = 3;
first_div.role = ax::mojom::Role::kGenericContainer;
first_div.AddState(ax::mojom::State::kEditable);
first_div.AddState(ax::mojom::State::kRichlyEditable);
first_div.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData first_static_text;
first_static_text.id = 8;
first_static_text.role = ax::mojom::Role::kStaticText;
first_static_text.AddState(ax::mojom::State::kEditable);
first_static_text.AddState(ax::mojom::State::kRichlyEditable);
first_static_text.SetName("first");
AXNodeData parent_div;
parent_div.id = 4;
parent_div.role = ax::mojom::Role::kGenericContainer;
parent_div.AddState(ax::mojom::State::kEditable);
parent_div.AddState(ax::mojom::State::kRichlyEditable);
parent_div.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData span_noneditable;
span_noneditable.id = 13;
span_noneditable.role = ax::mojom::Role::kGenericContainer;
AXNodeData second_static_text;
second_static_text.id = 9;
second_static_text.role = ax::mojom::Role::kStaticText;
second_static_text.AddState(ax::mojom::State::kEditable);
second_static_text.AddState(ax::mojom::State::kRichlyEditable);
second_static_text.SetName("second");
AXNodeData hidden_br;
hidden_br.id = 15;
hidden_br.role = ax::mojom::Role::kGenericContainer;
hidden_br.AddState(ax::mojom::State::kIgnored);
hidden_br.AddState(ax::mojom::State::kInvisible);
hidden_br.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData third_div;
third_div.id = 5;
third_div.role = ax::mojom::Role::kGenericContainer;
third_div.AddState(ax::mojom::State::kEditable);
third_div.AddState(ax::mojom::State::kRichlyEditable);
third_div.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
true);
AXNodeData third_static_text;
third_static_text.id = 10;
third_static_text.role = ax::mojom::Role::kStaticText;
third_static_text.AddState(ax::mojom::State::kEditable);
third_static_text.AddState(ax::mojom::State::kRichlyEditable);
third_static_text.SetName("third");
root_data.child_ids = {editable_container.id};
editable_container.child_ids = {first_div.id, parent_div.id, third_div.id};
first_div.child_ids = {first_static_text.id};
parent_div.child_ids = {span_noneditable.id, second_static_text.id,
hidden_br.id};
third_div.child_ids = {third_static_text.id};
SetTree(
CreateAXTree({root_data, editable_container, first_div, first_static_text,
parent_div, span_noneditable, second_static_text, hidden_br,
third_div, third_static_text}));
TestPositionType text_position =
CreateTextPosition(parent_div, 0, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionType line_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kLineStart, ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, line_position);
EXPECT_TRUE(line_position->IsTextPosition());
EXPECT_EQ(parent_div.id, line_position->anchor_id());
EXPECT_EQ(6, line_position->text_offset());
line_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kLineStart, ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, line_position);
EXPECT_TRUE(line_position->IsTextPosition());
EXPECT_EQ(parent_div.id, line_position->anchor_id());
EXPECT_EQ(0, line_position->text_offset());
text_position =
CreateTextPosition(third_div, 4, ax::mojom::TextAffinity::kDownstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
line_position = text_position->CreatePositionAtTextBoundary(
ax::mojom::TextBoundary::kLineStart, ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
ASSERT_NE(nullptr, line_position);
EXPECT_TRUE(line_position->IsTextPosition());
EXPECT_EQ(third_div.id, line_position->anchor_id());
EXPECT_EQ(0, line_position->text_offset());
}
TEST_F(AXPositionTest, GetUnignoredSelectionWithLeafNodes) {
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kExposeCharacterForHypertext);
AXNodeData root_data;
root_data.id = 1;
root_data.role = ax::mojom::Role::kRootWebArea;
AXNodeData parent_data;
parent_data.id = 2;
parent_data.role = ax::mojom::Role::kGenericContainer;
AXNodeData child_1_data;
child_1_data.id = 3;
child_1_data.role = ax::mojom::Role::kGenericContainer;
AXNodeData child_2_data;
child_2_data.id = 4;
child_2_data.role = ax::mojom::Role::kGenericContainer;
root_data.child_ids = {parent_data.id};
parent_data.child_ids = {child_1_data.id, child_2_data.id};
AXTreeData data;
data.tree_id = AXTreeID::CreateNewAXTreeID();
data.parent_tree_id = AXTreeID();
data.sel_anchor_object_id = child_1_data.id;
data.sel_anchor_offset = 0;
data.sel_focus_object_id = child_1_data.id;
data.sel_focus_offset = 0;
AXTreeUpdate update;
update.tree_data = data;
update.has_tree_data = true;
update.root_id = root_data.id;
update.nodes = {root_data, parent_data, child_1_data, child_2_data};
SetTree(std::make_unique<AXTree>(update));
AXTree* tree = GetTree();
TestPositionType parent_at_0 = CreateTreePosition(parent_data, 0);
TestPositionType parent_at_1 = CreateTreePosition(parent_data, 1);
TestPositionType parent_at_2 = CreateTreePosition(parent_data, 2);
TestPositionType child_1_at_0 = CreateTreePosition(child_1_data, 0);
TestPositionType child_2_at_before_text =
CreateTreePosition(child_2_data, AXNodePosition::BEFORE_TEXT);
EXPECT_TRUE(parent_at_0->IsValid());
EXPECT_TRUE(parent_at_1->IsValid());
EXPECT_TRUE(parent_at_2->IsValid());
EXPECT_TRUE(child_1_at_0->IsValid());
EXPECT_TRUE(child_2_at_before_text->IsValid());
child_1_data.AddState(ax::mojom::State::kIgnored);
child_2_data.AddState(ax::mojom::State::kIgnored);
AXTreeUpdate add_invalid_state_update;
add_invalid_state_update.nodes = {child_1_data, child_2_data};
ASSERT_TRUE(tree->Unserialize(add_invalid_state_update));
AXNode& parent_node = *GetNode(parent_data.id);
EXPECT_TRUE(AXNodePosition::IsLeafNodeForTreePosition(parent_node));
EXPECT_TRUE(parent_at_1->IsLeafTreePosition());
TestPositionType parent_at_before_text =
CreateTreePosition(parent_data, AXNodePosition::BEFORE_TEXT);
EXPECT_TRUE(parent_at_before_text->IsValid());
EXPECT_FALSE(parent_at_0->IsValid());
EXPECT_FALSE(parent_at_1->IsValid());
EXPECT_TRUE(parent_at_2->IsValid());
EXPECT_TRUE(child_2_at_before_text->IsValid());
EXPECT_EQ(*parent_at_before_text, *parent_at_before_text->AsValidPosition());
EXPECT_EQ(*parent_at_2, *parent_at_0->AsValidPosition());
EXPECT_EQ(*parent_at_2, *parent_at_1->AsValidPosition());
EXPECT_EQ(*parent_at_2, *parent_at_2->AsValidPosition());
EXPECT_EQ(*parent_at_2, *child_1_at_0->AsValidPosition());
EXPECT_EQ(*parent_at_before_text, *child_2_at_before_text->AsValidPosition());
for (TestPositionType::pointer position :
{parent_at_0.get(), child_1_at_0.get(), child_2_at_before_text.get()}) {
AXNodePosition::AXPositionInstance valid = position->AsValidPosition();
EXPECT_TRUE(position->IsLeaf());
EXPECT_TRUE(valid->IsLeaf());
data.sel_anchor_object_id = position->anchor_id();
data.sel_anchor_offset = position->child_index();
data.sel_focus_object_id = position->anchor_id();
data.sel_focus_offset = position->child_index();
tree->UpdateDataForTesting(data);
AXSelection s = tree->GetUnignoredSelection();
int expected_offset = valid->AtEndOfAnchor()
? static_cast<int>(parent_node.GetChildCount())
: AXNodePosition::BEFORE_TEXT;
EXPECT_EQ(valid->anchor_id(), s.anchor_object_id);
EXPECT_EQ(valid->child_index(), expected_offset);
EXPECT_EQ(valid->anchor_id(), s.focus_object_id);
EXPECT_EQ(valid->child_index(), expected_offset);
}
}
TEST_P(AXPositionExpandToEnclosingTextBoundaryTestWithParam,
TextPositionBeforeLine2) {
TestPositionType text_position = CreateTextPosition(
text_field_, 7 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position->IsTextPosition());
TestPositionRange range = text_position->ExpandToEnclosingTextBoundary(
GetParam().boundary, GetParam().expand_behavior);
EXPECT_EQ(GetParam().expected_anchor_position, range.anchor()->ToString());
EXPECT_EQ(GetParam().expected_focus_position, range.focus()->ToString());
}
TEST_P(AXPositionCreatePositionAtTextBoundaryTestWithParam,
TextPositionBeforeStaticText) {
TestPositionType text_position = CreateTextPosition(
static_text2_, 0 , ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position->IsTextPosition());
text_position = text_position->CreatePositionAtTextBoundary(
GetParam().boundary, GetParam().direction, GetParam().movement_options);
EXPECT_NE(nullptr, text_position);
EXPECT_EQ(GetParam().expected_text_position, text_position->ToString());
}
TEST_P(AXPositionTextNavigationTestWithParam,
TraverseTreeStartingWithAffinityDownstream) {
TestPositionType text_position =
CreateTextPosition(GetParam().start_node_id, GetParam().start_offset,
ax::mojom::TextAffinity::kDownstream);
ASSERT_TRUE(text_position->IsTextPosition());
for (const std::string& expectation : GetParam().expectations) {
text_position = GetParam().TestMethod.Run(text_position);
EXPECT_NE(nullptr, text_position);
EXPECT_EQ(expectation, text_position->ToString());
}
}
TEST_P(AXPositionTextNavigationTestWithParam,
TraverseTreeStartingWithAffinityUpstream) {
TestPositionType text_position =
CreateTextPosition(GetParam().start_node_id, GetParam().start_offset,
ax::mojom::TextAffinity::kUpstream);
ASSERT_TRUE(text_position->IsTextPosition());
bool upstream_is_not_moved = GetParam().upstream_is_not_moved;
for (const std::string& expectation : GetParam().expectations) {
auto prev_position = text_position->Clone();
text_position = GetParam().TestMethod.Run(text_position);
EXPECT_NE(nullptr, text_position);
if (upstream_is_not_moved) {
EXPECT_EQ(*prev_position, *text_position);
} else {
EXPECT_EQ(expectation, text_position->ToString());
}
}
}
INSTANTIATE_TEST_SUITE_P(
ExpandToEnclosingTextBoundary,
AXPositionExpandToEnclosingTextBoundaryTestWithParam,
::testing::Values(
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kCharacter,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=8 affinity=downstream "
"annotated_text=Line 1\nL<i>ne 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kCharacter,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kFormatEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=upstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kFormatEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=7 affinity=upstream "
"annotated_text=Line 1\n<L>ine 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStart,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStart,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStartOrEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStartOrEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kObject, AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kObject,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStart,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStart,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStartOrEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStartOrEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStart,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStart,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStartOrEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStartOrEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 affinity=downstream "
"annotated_text=Line 1\nLine 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWebPage,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=1 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=9 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWebPage,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=1 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=9 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=11 affinity=downstream "
"annotated_text=Line 1\nLine< >2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=11 affinity=downstream "
"annotated_text=Line 1\nLine< >2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStart,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=12 affinity=downstream "
"annotated_text=Line 1\nLine <2>"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStart,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=5 affinity=downstream "
"annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStartOrEnd,
AXRangeExpandBehavior::kLeftFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=11 affinity=downstream "
"annotated_text=Line 1\nLine< >2"},
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStartOrEnd,
AXRangeExpandBehavior::kRightFirst,
"TextPosition anchor_id=4 text_offset=7 affinity=downstream "
"annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=11 affinity=downstream "
"annotated_text=Line 1\nLine< >2"}));
INSTANTIATE_TEST_SUITE_P(
CreatePositionAtTextBoundary,
AXPositionCreatePositionAtTextBoundaryTestWithParam,
::testing::Values(
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kCharacter,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kCharacter,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=1 affinity=downstream "
"annotated_text=L<i>ne 2"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kFormatStart,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kFormatEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStart,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStart,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"NullPosition"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStartOrEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kLineStartOrEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kObject,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kObject,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStart,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStart,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"NullPosition"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStartOrEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kParagraphStartOrEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStart,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStart,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"NullPosition"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStartOrEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kSentenceStartOrEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWebPage,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=1 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1\nLine 2"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWebPage,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=9 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=4 affinity=downstream "
"annotated_text=Line< >2"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStart,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=5 affinity=downstream "
"annotated_text=Line <1>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStart,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=5 affinity=downstream "
"annotated_text=Line <2>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStartOrEnd,
ax::mojom::MoveDirection::kBackward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=6 text_offset=5 affinity=downstream "
"annotated_text=Line <1>"},
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kWordStartOrEnd,
ax::mojom::MoveDirection::kForward,
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition},
"TextPosition anchor_id=8 text_offset=4 affinity=downstream "
"annotated_text=Line< >2"}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextSentenceEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousSentenceEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousSentenceEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=5 "
"affinity=downstream annotated_text=Line <1>",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=5 "
"affinity=downstream annotated_text=Line <1>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=5 "
"affinity=downstream annotated_text=Line <1>",
"TextPosition anchor_id=5 text_offset=5 "
"affinity=downstream annotated_text=Line <1>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>",
"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=5 "
"affinity=downstream annotated_text=Line <1>",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=5 "
"affinity=downstream annotated_text=Line <2>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=5 "
"affinity=downstream annotated_text=Line <1>",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=5 "
"affinity=downstream annotated_text=Line <1>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=12 "
"affinity=downstream annotated_text=Line 1\nLine <2>",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=5 "
"affinity=downstream annotated_text=Line <1>\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=5 "
"affinity=downstream annotated_text=Line <1>",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=4 "
"affinity=downstream annotated_text=Line< >2",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=4 "
"affinity=downstream annotated_text=Line< >2"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=4 "
"affinity=downstream annotated_text=Line< >2",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"TextPosition anchor_id=6 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=4 "
"affinity=downstream annotated_text=Line< >2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=11 "
"affinity=downstream annotated_text=Line 1\nLine< >2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=4 "
"affinity=downstream annotated_text=Line< >1\nLine 2",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"TextPosition anchor_id=6 text_offset=4 "
"affinity=downstream annotated_text=Line< >1",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"NullPosition"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"NullPosition"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"NullPosition"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"NullPosition"},
true}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"},
true}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"},
true}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"},
true},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"},
true}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
5 ,
{"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=7 text_offset=0 "
"affinity=downstream annotated_text=<\n>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
5 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
12 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
12 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX1_ID,
2 ,
{"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1",
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
5 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=7 text_offset=0 "
"affinity=downstream annotated_text=<\n>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=2 text_offset=0 "
"affinity=downstream annotated_text=<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 affinity=downstream "
"annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 affinity=downstream "
"annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=7 "
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
5 ,
{"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=5 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 2",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1",
"TextPosition anchor_id=6 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=6 affinity=downstream "
"annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
LINE_BREAK_ID,
0 ,
{"TextPosition anchor_id=7 text_offset=1 affinity=downstream "
"annotated_text=\n<>",
"TextPosition anchor_id=7 text_offset=1 affinity=downstream "
"annotated_text=\n<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
LINE_BREAK_ID,
1 ,
{"TextPosition anchor_id=7 text_offset=1 affinity=downstream "
"annotated_text=\n<>",
"TextPosition anchor_id=7 text_offset=1 affinity=downstream "
"annotated_text=\n<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
0 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=1 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
0 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"TextPosition anchor_id=4 text_offset=13 "
"affinity=downstream annotated_text=Line 1\nLine 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
STATIC_TEXT1_ID,
1 ,
{"TextPosition anchor_id=5 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>",
"TextPosition anchor_id=9 text_offset=6 "
"affinity=downstream annotated_text=Line 2<>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
5 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"NullPosition"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kCrossBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=6 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=3 text_offset=0 affinity=downstream "
"annotated_text=<>",
"NullPosition"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
5 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=4 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorStopAtAnchorBoundaryOrIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
ROOT_ID,
12 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
TEXT_FIELD_ID,
12 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX1_ID,
2 ,
{"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1",
"TextPosition anchor_id=6 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 1"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2",
"TextPosition anchor_id=9 text_offset=0 affinity=downstream "
"annotated_text=<L>ine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
LINE_BREAK_ID,
0 ,
{"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>",
"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtAnchorBoundary,
AXBoundaryDetection::kCheckInitialPosition});
}),
LINE_BREAK_ID,
1 ,
{"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>",
"TextPosition anchor_id=7 text_offset=0 affinity=downstream "
"annotated_text=<\n>"}}));
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
13 ,
{"TextPosition anchor_id=1 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
13 ,
{"TextPosition anchor_id=4 text_offset=6 "
"affinity=downstream annotated_text=Line 1<\n>Line 2",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
ROOT_ID,
5 ,
{"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2",
"TextPosition anchor_id=1 text_offset=0 "
"affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
TEXT_FIELD_ID,
5 ,
{"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
4 ,
{"TextPosition anchor_id=6 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>"}},
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
{AXBoundaryBehavior::kStopAtLastAnchorBoundary,
AXBoundaryDetection::kDontCheckInitialPosition});
}),
INLINE_BOX2_ID,
0 ,
{"TextPosition anchor_id=6 text_offset=6 "
"affinity=downstream annotated_text=Line 1<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>",
"TextPosition anchor_id=3 text_offset=0 "
"affinity=downstream annotated_text=<>"}}));
}