123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- // Copyright 2021 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/accessibility/ax_computed_node_data.h"
- #include <memory>
- #include <utility>
- #include <vector>
- #include "base/memory/raw_ptr.h"
- #include "testing/gmock/include/gmock/gmock-matchers.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/accessibility/ax_enums.mojom.h"
- #include "ui/accessibility/ax_node_data.h"
- #include "ui/accessibility/ax_node_id_forward.h"
- #include "ui/accessibility/ax_position.h"
- #include "ui/accessibility/ax_tree.h"
- #include "ui/accessibility/ax_tree_data.h"
- #include "ui/accessibility/ax_tree_id.h"
- #include "ui/accessibility/test_ax_tree_manager.h"
- namespace ui {
- namespace {
- class AXComputedNodeDataTest : public ::testing::Test,
- public TestAXTreeManager {
- public:
- AXComputedNodeDataTest();
- ~AXComputedNodeDataTest() override;
- AXComputedNodeDataTest(const AXComputedNodeDataTest& other) = delete;
- AXComputedNodeDataTest& operator=(const AXComputedNodeDataTest& other) =
- delete;
- void SetUp() override;
- protected:
- // Numbers at the end of variable names indicate their position under the
- // root.
- AXNodeData root_;
- AXNodeData paragraph_0_;
- AXNodeData static_text_0_0_ignored_;
- AXNodeData paragraph_1_ignored_;
- AXNodeData static_text_1_0_;
- AXNodeData paragraph_2_ignored_;
- AXNodeData link_2_0_ignored_;
- AXNodeData static_text_2_0_0_;
- AXNodeData static_text_2_0_1_;
- raw_ptr<AXNode> root_node_;
- };
- AXComputedNodeDataTest::AXComputedNodeDataTest() = default;
- AXComputedNodeDataTest::~AXComputedNodeDataTest() = default;
- void AXComputedNodeDataTest::SetUp() {
- // ++kRootWebArea contenteditable
- // ++++kParagraph
- // ++++++kStaticText IGNORED "i"
- // ++++kParagraph IGNORED
- // ++++++kStaticText "t_1"
- // ++++kParagraph IGNORED
- // ++++++kLink IGNORED
- // ++++++++kStaticText "s+t++2...0. 0"
- // ++++++++kStaticText "s t\n2\r0\r\n1"
- root_.id = 1;
- paragraph_0_.id = 2;
- static_text_0_0_ignored_.id = 3;
- paragraph_1_ignored_.id = 4;
- static_text_1_0_.id = 5;
- paragraph_2_ignored_.id = 6;
- link_2_0_ignored_.id = 7;
- static_text_2_0_0_.id = 8;
- static_text_2_0_1_.id = 9;
- root_.role = ax::mojom::Role::kRootWebArea;
- root_.AddBoolAttribute(ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot,
- true);
- root_.child_ids = {paragraph_0_.id, paragraph_1_ignored_.id,
- paragraph_2_ignored_.id};
- paragraph_0_.role = ax::mojom::Role::kParagraph;
- paragraph_0_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
- true);
- paragraph_0_.child_ids = {static_text_0_0_ignored_.id};
- static_text_0_0_ignored_.role = ax::mojom::Role::kStaticText;
- static_text_0_0_ignored_.AddState(ax::mojom::State::kIgnored);
- // Ignored text should not appear anywhere and should not be used to separate
- // words.
- static_text_0_0_ignored_.SetName("i");
- paragraph_1_ignored_.role = ax::mojom::Role::kParagraph;
- paragraph_1_ignored_.AddState(ax::mojom::State::kIgnored);
- paragraph_1_ignored_.AddBoolAttribute(
- ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
- paragraph_1_ignored_.child_ids = {static_text_1_0_.id};
- static_text_1_0_.role = ax::mojom::Role::kStaticText;
- // An underscore should separate words.
- static_text_1_0_.SetName("t_1");
- paragraph_2_ignored_.role = ax::mojom::Role::kParagraph;
- paragraph_2_ignored_.AddState(ax::mojom::State::kIgnored);
- paragraph_2_ignored_.AddBoolAttribute(
- ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
- paragraph_2_ignored_.child_ids = {link_2_0_ignored_.id};
- link_2_0_ignored_.role = ax::mojom::Role::kLink;
- link_2_0_ignored_.AddState(ax::mojom::State::kLinked);
- link_2_0_ignored_.AddState(ax::mojom::State::kIgnored);
- link_2_0_ignored_.child_ids = {static_text_2_0_0_.id, static_text_2_0_1_.id};
- static_text_2_0_0_.role = ax::mojom::Role::kStaticText;
- // A series of punctuation marks, or a stretch of whitespace should separate
- // words.
- static_text_2_0_0_.SetName("s+t++2...0. 0");
- static_text_2_0_1_.role = ax::mojom::Role::kStaticText;
- // Both a carage return as well as a line break should separate lines, but not
- // a space character.
- static_text_2_0_1_.SetName("s t\n2\r0\r\n1");
- AXTreeUpdate initial_state;
- initial_state.root_id = root_.id;
- initial_state.nodes = {root_,
- paragraph_0_,
- static_text_0_0_ignored_,
- paragraph_1_ignored_,
- static_text_1_0_,
- paragraph_2_ignored_,
- link_2_0_ignored_,
- static_text_2_0_0_,
- static_text_2_0_1_};
- initial_state.has_tree_data = true;
- AXTreeData tree_data;
- tree_data.tree_id = AXTreeID::CreateNewAXTreeID();
- tree_data.title = "Application";
- initial_state.tree_data = tree_data;
- auto tree = std::make_unique<AXTree>();
- ASSERT_TRUE(tree->Unserialize(initial_state)) << tree->error();
- root_node_ = tree->root();
- ASSERT_EQ(root_.id, root_node_->id());
- // `SetTree` is defined in our `TestAXTreeManager` superclass and it passes
- // ownership of the created AXTree to the manager.
- SetTree(std::move(tree));
- }
- } // namespace
- using ::testing::ElementsAre;
- using ::testing::ElementsAreArray;
- using ::testing::SizeIs;
- using ::testing::StrEq;
- TEST_F(AXComputedNodeDataTest, UnignoredValues) {
- const AXNode* paragraph_0_node = root_node_->GetChildAtIndex(0);
- const AXNode* static_text_0_0_ignored_node =
- paragraph_0_node->GetChildAtIndex(0);
- const AXNode* paragraph_1_ignored_node = root_node_->GetChildAtIndex(1);
- const AXNode* static_text_1_0_node =
- paragraph_1_ignored_node->GetChildAtIndex(0);
- const AXNode* paragraph_2_ignored_node = root_node_->GetChildAtIndex(2);
- const AXNode* link_2_0_ignored_node =
- paragraph_2_ignored_node->GetChildAtIndex(0);
- const AXNode* static_text_2_0_0_node =
- link_2_0_ignored_node->GetChildAtIndex(0);
- const AXNode* static_text_2_0_1_node =
- link_2_0_ignored_node->GetChildAtIndex(1);
- // Perform the checks twice to ensure that caching returns the same values.
- for (int i = 0; i < 2; ++i) {
- EXPECT_EQ(
- 0,
- root_node_->GetComputedNodeData().GetOrComputeUnignoredIndexInParent());
- EXPECT_EQ(0, paragraph_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredIndexInParent());
- EXPECT_EQ(1, static_text_1_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredIndexInParent());
- EXPECT_EQ(2, static_text_2_0_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredIndexInParent());
- EXPECT_EQ(3, static_text_2_0_1_node->GetComputedNodeData()
- .GetOrComputeUnignoredIndexInParent());
- EXPECT_EQ(
- kInvalidAXNodeID,
- root_node_->GetComputedNodeData().GetOrComputeUnignoredParentID());
- EXPECT_EQ(nullptr,
- root_node_->GetComputedNodeData().GetOrComputeUnignoredParent());
- EXPECT_FALSE(root_node_->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), paragraph_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(
- root_node_,
- paragraph_0_node->GetComputedNodeData().GetOrComputeUnignoredParent());
- EXPECT_FALSE(paragraph_0_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(paragraph_0_node->id(),
- static_text_0_0_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(paragraph_0_node,
- static_text_0_0_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_TRUE(static_text_0_0_ignored_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), paragraph_1_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(root_node_, paragraph_1_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_FALSE(paragraph_1_ignored_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), static_text_1_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(root_node_, static_text_1_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_FALSE(static_text_1_0_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), paragraph_2_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(root_node_, paragraph_2_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_FALSE(paragraph_2_ignored_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), link_2_0_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(root_node_, link_2_0_ignored_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_FALSE(link_2_0_ignored_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), static_text_2_0_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(root_node_, static_text_2_0_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_FALSE(static_text_2_0_0_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(root_node_->id(), static_text_2_0_1_node->GetComputedNodeData()
- .GetOrComputeUnignoredParentID());
- EXPECT_EQ(root_node_, static_text_2_0_1_node->GetComputedNodeData()
- .GetOrComputeUnignoredParent());
- EXPECT_FALSE(static_text_2_0_1_node->GetComputedNodeData()
- .GetOrComputeIsDescendantOfPlatformLeaf());
- EXPECT_EQ(
- 4, root_node_->GetComputedNodeData().GetOrComputeUnignoredChildCount());
- EXPECT_EQ(0, paragraph_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredChildCount());
- EXPECT_EQ(0, static_text_1_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredChildCount());
- EXPECT_EQ(0, static_text_2_0_0_node->GetComputedNodeData()
- .GetOrComputeUnignoredChildCount());
- EXPECT_EQ(0, static_text_2_0_1_node->GetComputedNodeData()
- .GetOrComputeUnignoredChildCount());
- EXPECT_THAT(
- root_node_->GetComputedNodeData().GetOrComputeUnignoredChildIDs(),
- ElementsAre(paragraph_0_.id, static_text_1_0_.id, static_text_2_0_0_.id,
- static_text_2_0_1_.id));
- }
- }
- TEST_F(AXComputedNodeDataTest, HasOrCanComputeAttribute) {
- EXPECT_TRUE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kValue));
- EXPECT_FALSE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kHtmlTag));
- EXPECT_TRUE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts));
- EXPECT_FALSE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds));
- AXNode* paragraph_0_node = root_node_->GetChildAtIndex(0);
- EXPECT_FALSE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kValue));
- EXPECT_FALSE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kHtmlTag));
- EXPECT_TRUE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts));
- EXPECT_FALSE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds));
- // By removing the `ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot`
- // attribute, the root is no longer a content editable.
- root_.RemoveBoolAttribute(ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot);
- root_.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
- {static_text_0_0_ignored_.id});
- paragraph_0_.AddStringAttribute(ax::mojom::StringAttribute::kValue,
- "New: \nvalue.");
- paragraph_0_.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, "p");
- paragraph_0_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
- {0, 4});
- AXTreeUpdate tree_update;
- tree_update.root_id = root_.id;
- tree_update.nodes = {root_, paragraph_0_};
- ASSERT_TRUE(GetTree()->Unserialize(tree_update));
- root_node_ = GetTree()->root();
- ASSERT_EQ(root_.id, root_node_->id());
- // Computing the value attribute is only supported on non-atomic text fields.
- EXPECT_FALSE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kValue));
- EXPECT_FALSE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kHtmlTag));
- EXPECT_TRUE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts));
- EXPECT_TRUE(root_node_->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds));
- paragraph_0_node = root_node_->GetChildAtIndex(0);
- // However, for maximum flexibility, if the value attribute is already present
- // in the node's data we should use it without checking if the role supports
- // it.
- EXPECT_TRUE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kValue));
- EXPECT_TRUE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::StringAttribute::kHtmlTag));
- EXPECT_TRUE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts));
- EXPECT_FALSE(paragraph_0_node->GetComputedNodeData().HasOrCanComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds));
- }
- TEST_F(AXComputedNodeDataTest, GetOrComputeAttribute) {
- // Embedded object behavior is dependant on platform. We manually set it to a
- // specific value so that test results are consistent across platforms.
- ScopedAXEmbeddedObjectBehaviorSetter embedded_object_behaviour(
- AXEmbeddedObjectBehavior::kSuppressCharacter);
- // Line breaks should be inserted between each paragraph to mirror how HTML's
- // "textContent" works.
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kValue),
- StrEq("\nt_1\ns+t++2...0. 0s t\n2\r0\r\n1"));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kHtmlTag),
- StrEq(""));
- // Boundaries are delimited by a vertical bar, '|'.
- // Words: "|t|_|1s|+|t|++|2|...|0|. |0s| |t|\n|2|\r|0|\r\n|1|".
- int32_t word_starts[] = {0, 5, 8, 12, 16, 19, 21, 23, 26};
- int32_t word_ends[] = {4, 6, 9, 13, 18, 20, 22, 24, 27};
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts),
- ElementsAreArray(word_starts));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordEnds),
- ElementsAreArray(word_ends));
- // Lines: "|t_1s+t++2...0. 0s t|\n|2|\r|0|\r\n|1|".
- int32_t line_starts[] = {0, 21, 23, 26};
- int32_t line_ends[] = {21, 23, 26, 27};
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineStarts),
- ElementsAreArray(line_starts));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineEnds),
- ElementsAreArray(line_ends));
- // Sentences: "|t_1s+t++2...0.| |0s t|\n|2|\r|0|\r\n|1|".
- int32_t sentence_starts[] = {0, 21, 23, 26};
- int32_t sentence_ends[] = {21, 23, 26, 27};
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceStarts),
- ElementsAreArray(sentence_starts));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceEnds),
- ElementsAreArray(sentence_ends));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds),
- SizeIs(0));
- AXNode* paragraph_0_node = root_node_->GetChildAtIndex(0);
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kValue),
- StrEq(""))
- << "The static text child should be ignored.";
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kHtmlTag),
- StrEq(""));
- // Ignored text produces no boundaries.
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts),
- SizeIs(0));
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordEnds),
- SizeIs(0));
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineStarts),
- SizeIs(0));
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineEnds),
- SizeIs(0));
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceStarts),
- SizeIs(0));
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceEnds),
- SizeIs(0));
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds),
- SizeIs(0));
- // By removing the `ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot`
- // attribute, the root is no longer a content editable.
- root_.RemoveBoolAttribute(ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot);
- root_.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
- {static_text_0_0_ignored_.id});
- paragraph_0_.AddStringAttribute(ax::mojom::StringAttribute::kValue,
- "New: \nvalue.");
- paragraph_0_.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, "p");
- // Word starts/ends are intentionally set to the wrong values to ensure that
- // `AXNodeData` takes priority over `AXComputedNodeData` if present.
- std::vector<int32_t> wrong_word_starts = {1, 5};
- std::vector<int32_t> wrong_word_ends = {6, 8};
- paragraph_0_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
- wrong_word_starts);
- paragraph_0_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
- wrong_word_ends);
- AXTreeUpdate tree_update;
- tree_update.root_id = root_.id;
- tree_update.nodes = {root_, paragraph_0_};
- ASSERT_TRUE(GetTree()->Unserialize(tree_update));
- root_node_ = GetTree()->root();
- ASSERT_EQ(root_.id, root_node_->id());
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kValue),
- SizeIs(0))
- << "Computing the value attribute is only supported on non-atomic text "
- "fields.";
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kHtmlTag),
- SizeIs(0));
- // No change to the various boundaries should have been observed since the
- // root's text content hasn't changed.
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts),
- ElementsAreArray(word_starts));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordEnds),
- ElementsAreArray(word_ends));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineStarts),
- ElementsAreArray(line_starts));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineEnds),
- ElementsAreArray(line_ends));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceStarts),
- ElementsAreArray(sentence_starts));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceEnds),
- ElementsAreArray(sentence_ends));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds),
- ElementsAre(static_text_0_0_ignored_.id));
- paragraph_0_node = root_node_->GetChildAtIndex(0);
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kValue),
- StrEq("New: \nvalue."))
- << "For maximum flexibility, if the value attribute is already present "
- "in the node's data we should use it without checking if the role "
- "supports it.";
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttributeUTF8(
- ax::mojom::StringAttribute::kHtmlTag),
- StrEq("p"));
- // Word starts/ends are intentionally set to the wrong values in `AXNodeData`.
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordStarts),
- ElementsAreArray(wrong_word_starts))
- << "`AXNodeData` should take priority over `AXComputedNodeData`, if "
- "present.";
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kWordEnds),
- ElementsAreArray(wrong_word_ends))
- << "`AXNodeData` should take priority over `AXComputedNodeData`, if "
- "present.";
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineStarts),
- ElementsAre());
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLineEnds),
- ElementsAre());
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceStarts),
- ElementsAre());
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kSentenceEnds),
- ElementsAre());
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData().GetOrComputeAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds),
- SizeIs(0));
- }
- TEST_F(AXComputedNodeDataTest, GetOrComputeTextContent) {
- // Embedded object behavior is dependant on platform. We manually set it to a
- // specific value so that test results are consistent across platforms.
- ScopedAXEmbeddedObjectBehaviorSetter embedded_object_behaviour(
- AXEmbeddedObjectBehavior::kSuppressCharacter);
- EXPECT_THAT(root_node_->GetComputedNodeData()
- .GetOrComputeTextContentWithParagraphBreaksUTF8(),
- StrEq("\nt_1\ns+t++2...0. 0s t\n2\r0\r\n1"));
- EXPECT_THAT(root_node_->GetComputedNodeData().GetOrComputeTextContentUTF8(),
- StrEq("t_1s+t++2...0. 0s t\n2\r0\r\n1"));
- EXPECT_EQ(
- root_node_->GetComputedNodeData().GetOrComputeTextContentLengthUTF8(),
- 27);
- // Paragraph_0's text is ignored. Ignored text should not be visible.
- const AXNode* paragraph_0_node = root_node_->GetChildAtIndex(0);
- EXPECT_THAT(paragraph_0_node->GetComputedNodeData()
- .GetOrComputeTextContentWithParagraphBreaksUTF8(),
- StrEq(""));
- EXPECT_THAT(
- paragraph_0_node->GetComputedNodeData().GetOrComputeTextContentUTF8(),
- StrEq(""));
- EXPECT_EQ(paragraph_0_node->GetComputedNodeData()
- .GetOrComputeTextContentLengthUTF8(),
- 0);
- // The two incarnations of the "TextContent" methods should behave identically
- // when line breaks are manually inserted via e.g. a <br> element in HTML, as
- // this case demonstrates.
- const AXNode* paragraph_2_ignored_node = root_node_->GetChildAtIndex(2);
- EXPECT_THAT(paragraph_2_ignored_node->GetComputedNodeData()
- .GetOrComputeTextContentWithParagraphBreaksUTF8(),
- StrEq("s+t++2...0. 0s t\n2\r0\r\n1"));
- EXPECT_THAT(paragraph_2_ignored_node->GetComputedNodeData()
- .GetOrComputeTextContentUTF8(),
- StrEq("s+t++2...0. 0s t\n2\r0\r\n1"));
- EXPECT_EQ(paragraph_2_ignored_node->GetComputedNodeData()
- .GetOrComputeTextContentLengthUTF8(),
- 24);
- }
- } // namespace ui
|