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
bar");
EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter(
2)); // "foo|
bar"
EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(
3)); // "foo |
bar"
// Non-collapsed space as remaining text
SetBasicBody("f
bar");
EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter(
0)); // "f|
bar"
EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(
1)); // "f |
bar"
// Legacy layout fails in the remaining test case
if (!LayoutNGEnabled())
return;
// Collapsed space as remaining text
SetBasicBody("f
");
EXPECT_FALSE(
GetRemainingText()->IsBeforeNonCollapsedCharacter(0)); // "f|
"
EXPECT_FALSE(
GetRemainingText()->IsAfterNonCollapsedCharacter(1)); // "f |
"
}
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
xx", 2);
EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter(
1)); // "xx|
xx"
EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(
2)); // "xx |
xx"
// Entire remaining text as line wrapping
SetAhemBody("(x
xx", 2);
EXPECT_TRUE(GetRemainingText()->IsBeforeNonCollapsedCharacter(
0)); // "(x|
xx"
EXPECT_TRUE(GetRemainingText()->IsAfterNonCollapsedCharacter(
1)); // "(x |
xx"
}
TEST_P(ParameterizedLayoutTextFragmentTest, SetTextWithFirstLetter) {
// Note: |V8TestingScope| is needed for |Text::splitText()|.
V8TestingScope scope;
SetBodyInnerHTML(
""
"
a
");
const Element& sample = *GetElementById("sample");
// |letter_x| is "a" then "" finally "x"
Text& letter_x = *To
(sample.firstChild());
ASSERT_TRUE(letter_x.GetLayoutObject()->IsTextFragment());
EXPECT_TRUE(letter_x.GetLayoutObject()->GetFirstLetterPart());
EXPECT_TRUE(To(letter_x.GetLayoutObject())
->IsRemainingTextLayoutObject());
ASSERT_TRUE(letter_x.GetLayoutObject()->GetFirstLetterPart());
EXPECT_EQ("a", letter_x.GetLayoutObject()->GetFirstLetterPart()->GetText());
// Make "" "a"
Text& letter_a = *letter_x.splitText(0, ASSERT_NO_EXCEPTION);
UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(letter_a.GetLayoutObject()->IsTextFragment())
<< "'a' is still first-letter";
EXPECT_TRUE(letter_a.GetLayoutObject()->GetFirstLetterPart());
EXPECT_TRUE(To(letter_a.GetLayoutObject())
->IsRemainingTextLayoutObject());
ASSERT_TRUE(letter_a.GetLayoutObject()->GetFirstLetterPart());
EXPECT_EQ("a", letter_a.GetLayoutObject()->GetFirstLetterPart()->GetText());
EXPECT_FALSE(letter_x.GetLayoutObject())
<< "We don't have layout text for empty Text node.";
// Make "x" "a"
letter_x.setTextContent("x");
UpdateAllLifecyclePhasesForTest();
// See |FirstLetterPseudoElement::DetachLayoutTree()| which updates remaining
// part |LayoutTextFragment|.
EXPECT_TRUE(letter_a.GetLayoutObject()->IsTextFragment())
<< "We still use LayoutTextFragment for 'a'";
EXPECT_FALSE(letter_a.GetLayoutObject()->GetFirstLetterPart());
EXPECT_FALSE(To(letter_a.GetLayoutObject())
->IsRemainingTextLayoutObject());
EXPECT_FALSE(To(letter_a.GetLayoutObject())
->GetFirstLetterPseudoElement());
ASSERT_TRUE(letter_x.GetLayoutObject()->IsTextFragment())
<< "'x' is first letter-part";
EXPECT_TRUE(To(letter_x.GetLayoutObject())
->IsRemainingTextLayoutObject());
ASSERT_TRUE(letter_x.GetLayoutObject()->GetFirstLetterPart());
EXPECT_EQ("x", letter_x.GetLayoutObject()->GetFirstLetterPart()->GetText());
}
// For http://crbug.com/984389
TEST_P(ParameterizedLayoutTextFragmentTest, SplitTextWithZero) {
// Note: |V8TestingScope| is needed for |Text::splitText()|.
V8TestingScope scope;
SetBodyInnerHTML(
""
" x y
");
const Element& sample = *GetElementById("sample");
// Make " " "x y"
To(sample.firstChild())->splitText(1, ASSERT_NO_EXCEPTION);
UpdateAllLifecyclePhasesForTest();
// Make "" " " "x y"
To(sample.firstChild())->splitText(0, ASSERT_NO_EXCEPTION);
UpdateAllLifecyclePhasesForTest();
Text& xy = To(*sample.lastChild());
FirstLetterPseudoElement& first_letter_element =
*To(xy.GetLayoutObject())
->GetFirstLetterPseudoElement();
EXPECT_EQ(first_letter_element.GetLayoutObject(),
xy.GetLayoutObject()->PreviousSibling())
<< "first-letter remaining part should be next to first-letter part";
}
} // namespace blink