diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc index 0160daf039c..bb4c02b5cb0 100644 --- a/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc +++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc @@ -5,7 +5,12 @@ #include "third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/editing/ephemeral_range.h" +#include "third_party/blink/renderer/core/editing/markers/document_marker.h" +#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h" +#include "third_party/blink/renderer/core/editing/position.h" #include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h" +#include "third_party/blink/renderer/modules/accessibility/ax_range.h" #include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -38,5 +43,278 @@ TEST_P(ParameterizedAccessibilityTest, GetWordBoundaries) { EXPECT_EQ(expected_word_ends, word_ends); } +TEST_P(ParameterizedAccessibilityTest, GetDocumentMarkers) { + // There should be four inline text boxes in the following paragraph. + SetBodyInnerHTML(R"HTML( + <style>* { font-size: 10px; }</style> + <p id="paragraph" style="width: 10ch;"> + Misspelled text with a grammar error. + </p>)HTML"); + + const Node* text = GetElementById("paragraph")->firstChild(); + ASSERT_NE(nullptr, text); + ASSERT_TRUE(text->IsTextNode()); + + // Mark the part of the paragraph that says "Misspelled text" with a spelling + // marker, and the part that says "a grammar error" with a grammar marker. + // + // Note that the inline text boxes and the markers do not occupy the same text + // range. The ranges simply overlap. Also note that the marker ranges include + // non-collapsed white space found in the DOM. + DocumentMarkerController& marker_controller = GetDocument().Markers(); + const EphemeralRange misspelled_range(Position(text, 9), Position(text, 24)); + marker_controller.AddSpellingMarker(misspelled_range); + const EphemeralRange grammar_range(Position(text, 30), Position(text, 45)); + marker_controller.AddGrammarMarker(grammar_range); + + AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, ax_paragraph); + ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue()); + ax_paragraph->LoadInlineTextBoxes(); + + // kStaticText: "Misspelled text with a grammar error.". + const AXObject* ax_text = ax_paragraph->FirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_text); + ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text->RoleValue()); + ASSERT_EQ(4, ax_text->ChildCountIncludingIgnored()); + + // For each inline text box, angle brackets indicate where the marker starts + // and ends respectively. + + // kInlineTextBox: "<Misspelled >". + AXObject* ax_inline_text_box = ax_text->ChildAtIncludingIgnored(0); + ASSERT_NE(nullptr, ax_inline_text_box); + VectorOf<DocumentMarker::MarkerType> marker_types; + VectorOf<AXRange> marker_ranges; + ax_inline_text_box->GetDocumentMarkers(&marker_types, &marker_ranges); + EXPECT_EQ((VectorOf<DocumentMarker::MarkerType>{DocumentMarker::kSpelling}), + marker_types); + EXPECT_EQ( + (VectorOf<AXRange>{AXRange( + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 0), + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 11))}), + marker_ranges); + + // kInlineTextBox: "<text> with <a >". + ax_inline_text_box = ax_text->ChildAtIncludingIgnored(1); + ASSERT_NE(nullptr, ax_inline_text_box); + marker_types.clear(); + marker_ranges.clear(); + ax_inline_text_box->GetDocumentMarkers(&marker_types, &marker_ranges); + EXPECT_EQ((VectorOf<DocumentMarker::MarkerType>{DocumentMarker::kSpelling, + DocumentMarker::kGrammar}), + marker_types); + EXPECT_EQ( + (VectorOf<AXRange>{ + AXRange( + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 0), + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 4)), + AXRange( + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 10), + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, + 12))}), + marker_ranges); + + // kInlineTextBox: "<grammar >". + ax_inline_text_box = ax_text->ChildAtIncludingIgnored(2); + ASSERT_NE(nullptr, ax_inline_text_box); + marker_types.clear(); + marker_ranges.clear(); + ax_inline_text_box->GetDocumentMarkers(&marker_types, &marker_ranges); + EXPECT_EQ((VectorOf<DocumentMarker::MarkerType>{DocumentMarker::kGrammar}), + marker_types); + EXPECT_EQ( + (VectorOf<AXRange>{AXRange( + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 0), + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 8))}), + marker_ranges); + + // kInlineTextBox: "<error>.". + ax_inline_text_box = ax_text->ChildAtIncludingIgnored(3); + ASSERT_NE(nullptr, ax_inline_text_box); + marker_types.clear(); + marker_ranges.clear(); + ax_inline_text_box->GetDocumentMarkers(&marker_types, &marker_ranges); + EXPECT_EQ((VectorOf<DocumentMarker::MarkerType>{DocumentMarker::kGrammar}), + marker_types); + EXPECT_EQ( + (VectorOf<AXRange>{AXRange( + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 0), + AXPosition::CreatePositionInTextObject(*ax_inline_text_box, 5))}), + marker_ranges); +} + +TEST_P(ParameterizedAccessibilityTest, TextOffsetInContainerWithASpan) { + // There should be three inline text boxes in the following paragraph. The + // span should reset the text start offset of all of them to 0. + SetBodyInnerHTML(R"HTML( + <style>* { font-size: 10px; }</style> + <p id="paragraph"> + Hello <span>world </span>there. + </p>)HTML"); + + AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, ax_paragraph); + ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue()); + ax_paragraph->LoadInlineTextBoxes(); + + const AXObject* ax_inline_text_box = + ax_paragraph->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(1, ax_inline_text_box->TextOffsetInContainer(1)); + + ax_inline_text_box = ax_inline_text_box->NextInPreOrderIncludingIgnored() + ->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(2, ax_inline_text_box->TextOffsetInContainer(2)); + + ax_inline_text_box = ax_inline_text_box->NextInPreOrderIncludingIgnored() + ->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(3, ax_inline_text_box->TextOffsetInContainer(3)); + + ASSERT_EQ(nullptr, ax_inline_text_box->NextInPreOrderIncludingIgnored()); +} + +TEST_P(ParameterizedAccessibilityTest, + TextOffsetInContainerWithMultipleInlineTextBoxes) { + // There should be four inline text boxes in the following paragraph. The span + // should not affect the text start offset of the text outside the span. + SetBodyInnerHTML(R"HTML( + <style>* { font-size: 10px; }</style> + <p id="paragraph" style="width: 5ch;"> + <span>Offset</span>Hello world there. + </p>)HTML"); + + AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, ax_paragraph); + ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue()); + ax_paragraph->LoadInlineTextBoxes(); + + const AXObject* ax_inline_text_box = + ax_paragraph->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(1, ax_inline_text_box->TextOffsetInContainer(1)); + + ax_inline_text_box = ax_inline_text_box->NextInPreOrderIncludingIgnored() + ->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(1, ax_inline_text_box->TextOffsetInContainer(1)); + + ax_inline_text_box = ax_inline_text_box->NextSiblingIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(6, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(8, ax_inline_text_box->TextOffsetInContainer(2)); + + ax_inline_text_box = ax_inline_text_box->NextSiblingIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(12, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(15, ax_inline_text_box->TextOffsetInContainer(3)); + + ASSERT_EQ(nullptr, ax_inline_text_box->NextInPreOrderIncludingIgnored()); +} + +TEST_P(ParameterizedAccessibilityTest, TextOffsetInContainerWithLineBreak) { + // There should be three inline text boxes in the following paragraph. The + // line break should reset the text start offset to 0 of both the inline text + // box inside the line break, as well as the text start ofset of the second + // line. + SetBodyInnerHTML(R"HTML( + <style>* { font-size: 10px; }</style> + <p id="paragraph"> + Line one.<br> + Line two. + </p>)HTML"); + + AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, ax_paragraph); + ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue()); + ax_paragraph->LoadInlineTextBoxes(); + + const AXObject* ax_inline_text_box = + ax_paragraph->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(1, ax_inline_text_box->TextOffsetInContainer(1)); + + ax_inline_text_box = ax_inline_text_box->NextInPreOrderIncludingIgnored() + ->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + + ax_inline_text_box = ax_inline_text_box->NextInPreOrderIncludingIgnored() + ->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + EXPECT_EQ(0, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(2, ax_inline_text_box->TextOffsetInContainer(2)); + + ASSERT_EQ(nullptr, ax_inline_text_box->NextInPreOrderIncludingIgnored()); +} + +TEST_P(ParameterizedAccessibilityTest, TextOffsetInContainerWithBreakWord) { + // There should be three inline text boxes in the following paragraph because + // of the narrow width and the long word, coupled with the CSS "break-word" + // property. Each inline text box should have a different offset in container. + LoadAhem(); + SetBodyInnerHTML(R"HTML( + <style>* { font: 10px/10px Ahem; }</style> + <p id="paragraph" style="width: 5ch; word-wrap: break-word;"> + VeryLongWord + </p>)HTML"); + + AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, ax_paragraph); + ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue()); + ax_paragraph->LoadInlineTextBoxes(); + + const AXObject* ax_inline_text_box = + ax_paragraph->DeepestFirstChildIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + + int text_start_offset = 0; + int text_end_offset = ax_inline_text_box->TextLength(); + EXPECT_EQ(text_start_offset, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(text_end_offset, ax_inline_text_box->TextOffsetInContainer( + ax_inline_text_box->TextLength())); + + ax_inline_text_box = ax_inline_text_box->NextSiblingIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + + text_start_offset = text_end_offset; + text_end_offset = text_start_offset + ax_inline_text_box->TextLength(); + EXPECT_EQ(text_start_offset, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(text_end_offset, ax_inline_text_box->TextOffsetInContainer( + ax_inline_text_box->TextLength())); + + ax_inline_text_box = ax_inline_text_box->NextSiblingIncludingIgnored(); + ASSERT_NE(nullptr, ax_inline_text_box); + ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue()); + + text_start_offset = text_end_offset; + text_end_offset = text_start_offset + ax_inline_text_box->TextLength(); + EXPECT_EQ(text_start_offset, ax_inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(text_end_offset, ax_inline_text_box->TextOffsetInContainer( + ax_inline_text_box->TextLength())); + + ASSERT_EQ(nullptr, ax_inline_text_box->NextSiblingIncludingIgnored()); +} + } // namespace test } // namespace blink |