| // Copyright 2017 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 "third_party/blink/renderer/core/layout/layout_text_fragment.h" |
| |
| #include "third_party/blink/renderer/core/html/html_head_element.h" |
| #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" |
| #include "third_party/blink/renderer/platform/runtime_enabled_features.h" |
| #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" |
| |
| namespace blink { |
| |
| class LayoutTextFragmentTest : public RenderingTest { |
| protected: |
| void SetUp() override { |
| RenderingTest::SetUp(); |
| GetDocument().head()->SetInnerHTMLFromString( |
| "<style>#target::first-letter{color:red}</style>"); |
| } |
| |
| void SetBasicBody(const char* message) { |
| SetBodyInnerHTML(String::Format( |
| "<div id='target' style='font-size: 10px;'>%s</div>", message)); |
| } |
| |
| void SetAhemBody(const char* message, const unsigned width) { |
| SetBodyInnerHTML(String::Format( |
| "<div id='target' style='font: 10px Ahem; width: %uem'>%s</div>", width, |
| message)); |
| } |
| |
| const LayoutTextFragment* GetRemainingText() const { |
| return ToLayoutTextFragment( |
| GetElementById("target")->firstChild()->GetLayoutObject()); |
| } |
| |
| const LayoutTextFragment* GetFirstLetter() const { |
| return ToLayoutTextFragment( |
| AssociatedLayoutObjectOf(*GetElementById("target")->firstChild(), 0)); |
| } |
| }; |
| |
| // Helper class to run the same test code with and without LayoutNG |
| class ParameterizedLayoutTextFragmentTest |
| : public testing::WithParamInterface<bool>, |
| private ScopedLayoutNGForTest, |
| public LayoutTextFragmentTest { |
| public: |
| ParameterizedLayoutTextFragmentTest() : ScopedLayoutNGForTest(GetParam()) {} |
| |
| protected: |
| bool LayoutNGEnabled() const { return GetParam(); } |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| ParameterizedLayoutTextFragmentTest, |
| testing::Bool()); |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, Basics) { |
| SetBasicBody("foo"); |
| |
| EXPECT_EQ(0, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(1, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(1u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(0)); |
| |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| EXPECT_EQ(2u, GetRemainingText()->ResolvedTextLength()); |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, CaretMinMaxOffset) { |
| SetBasicBody("(f)oo"); |
| EXPECT_EQ(0, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(3, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody(" (f)oo"); |
| EXPECT_EQ(2, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(5, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody("(f)oo "); |
| EXPECT_EQ(0, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(3, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody(" (f)oo "); |
| EXPECT_EQ(1, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(4, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, CaretMinMaxOffsetSpacesInBetween) { |
| SetBasicBody("(f) oo"); |
| EXPECT_EQ(0, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(3, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(4, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody(" (f) oo"); |
| EXPECT_EQ(2, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(5, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(4, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody("(f) oo "); |
| EXPECT_EQ(0, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(3, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(4, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody(" (f) oo "); |
| EXPECT_EQ(1, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(4, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(4, GetRemainingText()->CaretMaxOffset()); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, |
| CaretMinMaxOffsetCollapsedRemainingText) { |
| // Tests if the NG implementation matches the legacy behavior that, when the |
| // remaining text is fully collapsed, its CaretMin/MaxOffset() return 0 and |
| // FragmentLength(). |
| |
| SetBasicBody("(f) "); |
| EXPECT_EQ(0, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(3, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| |
| SetBasicBody(" (f) "); |
| EXPECT_EQ(2, GetFirstLetter()->CaretMinOffset()); |
| EXPECT_EQ(5, GetFirstLetter()->CaretMaxOffset()); |
| EXPECT_EQ(0, GetRemainingText()->CaretMinOffset()); |
| EXPECT_EQ(2, GetRemainingText()->CaretMaxOffset()); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, ResolvedTextLength) { |
| SetBasicBody("(f)oo"); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(2u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody(" (f)oo"); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(2u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody("(f)oo "); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(2u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody(" (f)oo "); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(2u, GetRemainingText()->ResolvedTextLength()); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, ResolvedTextLengthSpacesInBetween) { |
| SetBasicBody("(f) oo"); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(3u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody(" (f) oo"); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(3u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody("(f) oo "); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(3u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody(" (f) oo "); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(3u, GetRemainingText()->ResolvedTextLength()); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, |
| ResolvedTextLengthCollapsedRemainingText) { |
| SetBasicBody("(f) "); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(0u, GetRemainingText()->ResolvedTextLength()); |
| |
| SetBasicBody(" (f) "); |
| EXPECT_EQ(3u, GetFirstLetter()->ResolvedTextLength()); |
| EXPECT_EQ(0u, GetRemainingText()->ResolvedTextLength()); |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, ContainsCaretOffset) { |
| SetBasicBody("(f)oo"); |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(0)); // "|(f)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(1)); // "(|f)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(2)); // "(f|)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(3)); // "(f)|oo" |
| EXPECT_FALSE(GetFirstLetter()->ContainsCaretOffset(4)); // out of range |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); // "(f)|oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // "(f)o|o" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(2)); // "(f)oo|" |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(3)); // out of range |
| |
| SetBasicBody(" (f)oo"); |
| EXPECT_FALSE(GetFirstLetter()->ContainsCaretOffset(0)); // "| (f)oo" |
| EXPECT_FALSE(GetFirstLetter()->ContainsCaretOffset(1)); // " | (f)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(2)); // " |(f)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(3)); // " (|f)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(4)); // " (f|)oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(5)); // " (f)|oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); // " (f)|oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // " (f)o|o" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(2)); // " (f)oo|" |
| |
| SetBasicBody("(f)oo "); |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(0)); // "|(f)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(1)); // "(|f)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(2)); // "(f|)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(3)); // "(f)|oo " |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); // "(f)|oo " |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // "(f)o|o " |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(2)); // "(f)oo| " |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(3)); // "(f)oo | " |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(4)); // "(f)oo |" |
| |
| SetBasicBody(" (f)oo "); |
| EXPECT_FALSE(GetFirstLetter()->ContainsCaretOffset(0)); // "| (f)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(1)); // " |(f)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(2)); // " (|f)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(3)); // " (f|)oo " |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(4)); // " (f)|oo " |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); // " (f)|oo " |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // " (f)o|o " |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(2)); // " (f)oo| " |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(3)); // " (f)oo | " |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(4)); // " (f)oo |" |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, |
| ContainsCaretOffsetSpacesInBetween) { |
| SetBasicBody("(f) oo"); |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(0)); // "|(f) oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(1)); // "(|f) oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(2)); // "(f|) oo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(3)); // "(f)| oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); // "(f)| oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // "(f) | oo" |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(2)); // "(f) | oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(3)); // "(f) |oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(4)); // "(f) o|o" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(5)); // "(f) oo|" |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, ContainsCaretOffsetPre) { |
| SetBodyInnerHTML("<pre id='target'>(f) oo\n</pre>"); |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(0)); // "|(f) oo\n" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(1)); // "(|f) oo\n" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(2)); // "(f|) oo\n" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(3)); // "(f)| oo\n" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(0)); // "(f)| oo\n" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // "(f) | oo\n" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(2)); // "(f) | oo\n" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(3)); // "(f) |oo\n" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(4)); // "(f) o|o\n" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(5)); // "(f) oo|\n" |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(6)); // "(f) oo\n|" |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, ContainsCaretOffsetPreLine) { |
| SetBodyInnerHTML("<div id='target' style='white-space: pre-line'>F \n \noo"); |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(0)); // "|F \n \noo" |
| EXPECT_TRUE(GetFirstLetter()->ContainsCaretOffset(1)); // "F| \n \noo" |
| |
| if (LayoutNGEnabled()) { |
| // Legacy layout doesn't collapse this space correctly. |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(0)); // "F| \n \noo" |
| } |
| |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(1)); // "F |\n \noo" |
| EXPECT_FALSE(GetRemainingText()->ContainsCaretOffset(2)); // "F \n| \noo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(3)); // "F \n |\noo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(4)); // "F \n \n|oo" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(5)); // "F \n \no|o" |
| EXPECT_TRUE(GetRemainingText()->ContainsCaretOffset(6)); // "F \n \noo|" |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, |
| IsBeforeAfterNonCollapsedCharacterNoLineWrap) { |
| // Basic tests |
| SetBasicBody("foo"); |
| EXPECT_TRUE(GetFirstLetter()->IsBeforeNonCollapsedCharacter(0)); // "|foo" |
| EXPECT_TRUE(GetFirstLetter()->IsAfterNonCollapsedCharacter(1)); // "f|oo" |
| EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter(0)); // "f|oo" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(2)); // "foo|" |
| |
| // Return false at layout object end/start, respectively |
| EXPECT_FALSE(GetFirstLetter()->IsAfterNonCollapsedCharacter(0)); // "|foo" |
| EXPECT_FALSE(GetFirstLetter()->IsBeforeNonCollapsedCharacter(1)); // "f|oo" |
| EXPECT_FALSE(GetRemainingText()->IsAfterNonCollapsedCharacter(0)); // "f|oo" |
| EXPECT_FALSE(GetRemainingText()->IsBeforeNonCollapsedCharacter(2)); // "foo|" |
| |
| // Consecutive spaces between first letter and remaining text |
| SetBasicBody("f bar"); |
| EXPECT_TRUE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(0)); // "f| bar" |
| EXPECT_FALSE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(1)); // "f | bar" |
| EXPECT_FALSE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(2)); // "f | bar" |
| EXPECT_TRUE( |
| GetRemainingText()->IsAfterNonCollapsedCharacter(1)); // "f | bar" |
| EXPECT_FALSE( |
| GetRemainingText()->IsAfterNonCollapsedCharacter(2)); // "f | bar" |
| EXPECT_FALSE( |
| GetRemainingText()->IsAfterNonCollapsedCharacter(3)); // "f |bar" |
| |
| // Leading spaces in first letter are collapsed |
| SetBasicBody(" foo"); |
| EXPECT_FALSE(GetFirstLetter()->IsBeforeNonCollapsedCharacter(0)); // "| foo" |
| EXPECT_FALSE(GetFirstLetter()->IsBeforeNonCollapsedCharacter(1)); // " | foo" |
| EXPECT_FALSE(GetFirstLetter()->IsAfterNonCollapsedCharacter(1)); // " | foo" |
| EXPECT_FALSE(GetFirstLetter()->IsAfterNonCollapsedCharacter(2)); // " |foo" |
| |
| // Trailing spaces in remaining text, when at the end of block, are collapsed |
| SetBasicBody("foo "); |
| EXPECT_FALSE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(2)); // "foo| " |
| EXPECT_FALSE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(3)); // "foo | " |
| EXPECT_FALSE( |
| GetRemainingText()->IsAfterNonCollapsedCharacter(3)); // "foo | " |
| EXPECT_FALSE(GetRemainingText()->IsAfterNonCollapsedCharacter(4)); // "foo |" |
| |
| // Non-collapsed space at remaining text end |
| SetBasicBody("foo <span>bar</span>"); |
| EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter( |
| 2)); // "foo| <span>bar</span>" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter( |
| 3)); // "foo |<span>bar</span>" |
| |
| // Non-collapsed space as remaining text |
| SetBasicBody("f <span>bar</span>"); |
| EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter( |
| 0)); // "f| <span>bar</span>" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter( |
| 1)); // "f |<span>bar</span>" |
| |
| // Legacy layout fails in the remaining test case |
| if (!LayoutNGEnabled()) |
| return; |
| |
| // Collapsed space as remaining text |
| SetBasicBody("f <br>"); |
| EXPECT_FALSE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(0)); // "f| <br>" |
| EXPECT_FALSE( |
| GetRemainingText()->IsAfterNonCollapsedCharacter(1)); // "f |<br>" |
| } |
| |
| TEST_P(ParameterizedLayoutTextFragmentTest, |
| IsBeforeAfterNonCollapsedLineWrapSpace) { |
| LoadAhem(); |
| |
| // Line wrapping in the middle of remaining text |
| SetAhemBody("xx xx", 2); |
| EXPECT_TRUE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(1)); // "xx| xx" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(2)); // "xx |xx" |
| |
| // Legacy layout fails in the remaining test cases |
| if (!LayoutNGEnabled()) |
| return; |
| |
| // Line wrapping at remaining text start |
| SetAhemBody("(x xx", 2); |
| EXPECT_TRUE( |
| GetRemainingText()->IsBeforeNonCollapsedCharacter(0)); // "(x| xx" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(1)); // "(x |xx" |
| |
| // Line wrapping at remaining text end |
| SetAhemBody("xx <span>xx</span>", 2); |
| EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter( |
| 1)); // "xx| <span>xx</span>" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter( |
| 2)); // "xx |<span>xx</span>" |
| |
| // Entire remaining text as line wrapping |
| SetAhemBody("(x <span>xx</span>", 2); |
| EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter( |
| 0)); // "(x| <span>xx</span>" |
| EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter( |
| 1)); // "(x |<span>xx</span>" |
| } |
| |
| } // namespace blink |