blob: 7b83b9df06d396e2cf285b1be557662a7ef9a998 [file] [log] [blame]
// Copyright 2019 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 "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/layout/line/abstract_inline_text_box.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 AbstractInlineTextBoxTest : public testing::WithParamInterface<bool>,
private ScopedLayoutNGForTest,
public RenderingTest {
public:
AbstractInlineTextBoxTest() : ScopedLayoutNGForTest(GetParam()) {}
protected:
bool LayoutNGEnabled() const {
return RuntimeEnabledFeatures::LayoutNGEnabled();
}
};
INSTANTIATE_TEST_SUITE_P(All, AbstractInlineTextBoxTest, testing::Bool());
TEST_P(AbstractInlineTextBoxTest, GetTextWithCollapsedWhiteSpace) {
SetBodyInnerHTML(R"HTML(
<style>* { font-size: 10px; }</style>
<div id="target">abc </div>)HTML");
const Element& target = *GetDocument().getElementById("target");
auto& layout_text = *To<LayoutText>(target.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box =
layout_text.FirstAbstractInlineTextBox();
EXPECT_EQ("abc", inline_text_box->GetText());
EXPECT_EQ(3u, inline_text_box->Len());
EXPECT_FALSE(inline_text_box->NeedsTrailingSpace());
}
// For DumpAccessibilityTreeTest.AccessibilityInputTextValue/blink
TEST_P(AbstractInlineTextBoxTest, GetTextWithLineBreakAtCollapsedWhiteSpace) {
// Line break at space between <label> and <input>.
SetBodyInnerHTML(R"HTML(
<style>* { font-size: 10px; }</style>
<div style="width: 10ch"><label id=label>abc:</label> <input></div>)HTML");
const Element& label = *GetDocument().getElementById("label");
auto& layout_text = *To<LayoutText>(label.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box =
layout_text.FirstAbstractInlineTextBox();
EXPECT_EQ("abc:", inline_text_box->GetText());
EXPECT_EQ(4u, inline_text_box->Len());
EXPECT_FALSE(inline_text_box->NeedsTrailingSpace());
}
// For "web_tests/accessibility/inline-text-change-style.html"
TEST_P(AbstractInlineTextBoxTest,
GetTextWithLineBreakAtMiddleCollapsedWhiteSpace) {
// There should be a line break at the space after "012".
SetBodyInnerHTML(R"HTML(
<style>* { font-size: 10px; }</style>
<div id="target" style="width: 0ch">012 345</div>)HTML");
const Element& target = *GetDocument().getElementById("target");
auto& layout_text = *To<LayoutText>(target.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box =
layout_text.FirstAbstractInlineTextBox();
EXPECT_EQ("012 ", inline_text_box->GetText());
EXPECT_EQ(4u, inline_text_box->Len());
EXPECT_TRUE(inline_text_box->NeedsTrailingSpace());
}
// DumpAccessibilityTreeTest.AccessibilitySpanLineBreak/blink
TEST_P(AbstractInlineTextBoxTest,
GetTextWithLineBreakAtSpanCollapsedWhiteSpace) {
// There should be a line break at the space in <span>.
SetBodyInnerHTML(R"HTML(
<style>* { font-size: 10px; }</style>
<p id="t1" style="width: 0ch">012<span id="t2"> </span>345</p>)HTML");
const Element& target1 = *GetDocument().getElementById("t1");
auto& layout_text1 = *To<LayoutText>(target1.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box1 =
layout_text1.FirstAbstractInlineTextBox();
EXPECT_EQ("012", inline_text_box1->GetText());
EXPECT_EQ(3u, inline_text_box1->Len());
EXPECT_FALSE(inline_text_box1->NeedsTrailingSpace());
const Element& target2 = *GetDocument().getElementById("t2");
auto& layout_text2 = *To<LayoutText>(target2.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box2 =
layout_text2.FirstAbstractInlineTextBox();
EXPECT_EQ(nullptr, inline_text_box2)
<< "We don't have inline box when <span> "
"contains only collapsed white spaces.";
}
// For DumpAccessibilityTreeTest.AccessibilityInputTypes/blink
TEST_P(AbstractInlineTextBoxTest, GetTextWithLineBreakAtTrailingWhiteSpace) {
// There should be a line break at the space of "abc: ".
SetBodyInnerHTML(R"HTML(
<style>* { font-size: 10px; }</style>
<div style="width: 10ch"><label id=label>abc: <input></label></div>)HTML");
const Element& label = *GetDocument().getElementById("label");
auto& layout_text = *To<LayoutText>(label.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box =
layout_text.FirstAbstractInlineTextBox();
EXPECT_EQ("abc: ", inline_text_box->GetText());
EXPECT_EQ(5u, inline_text_box->Len());
if (LayoutNGEnabled()) {
EXPECT_TRUE(inline_text_box->NeedsTrailingSpace());
} else {
EXPECT_FALSE(inline_text_box->NeedsTrailingSpace());
}
}
TEST_P(AbstractInlineTextBoxTest, GetTextOffsetInFormattingContext) {
// The span should not affect the offset in container of the following inline
// text boxes in the paragraph.
//
// Note that "&#10" is a Line Feed, ("\n").
SetBodyInnerHTML(R"HTML(
<style>p { white-space: pre-line; }</style>
<p id="paragraph"><span>Offset</span>First sentence &#10; of the paragraph. Second sentence of &#10; the paragraph.</p>
<br id="br">)HTML");
const Element& paragraph = *GetDocument().getElementById("paragraph");
const Node& text_node = *paragraph.firstChild()->nextSibling();
auto& layout_text = *To<LayoutText>(text_node.GetLayoutObject());
// The above "layout_text" should create five AbstractInlineTextBoxes:
// 1. "First sentence "
// 2. "\n"
// 3. "of the paragraph. Second sentence of "
// 4." \n"
// 5. "the paragraph."
//
// The AbstractInlineTextBoxes are all children of the same text node and an
// an offset calculated in the container node should always be the same for
// both LayoutNG and Legacy, even though Legacy doesn't collapse the
// white spaces at the end of an AbstractInlineTextBox. White spaces at the
// beginning of the third and fifth inline text box should be collapsed.
scoped_refptr<AbstractInlineTextBox> inline_text_box =
layout_text.FirstAbstractInlineTextBox();
String text = "First sentence";
EXPECT_EQ(LayoutNGEnabled() ? text : text + " ", inline_text_box->GetText());
EXPECT_EQ(6u, inline_text_box->TextOffsetInFormattingContext(0));
// We need to jump over the AbstractInlineTextBox with the line break.
inline_text_box = inline_text_box->NextInlineTextBox()->NextInlineTextBox();
text = "of the paragraph. Second sentence of";
EXPECT_EQ(LayoutNGEnabled() ? text : text + " ", inline_text_box->GetText());
EXPECT_EQ(21u, inline_text_box->TextOffsetInFormattingContext(0u));
// See comment above.
inline_text_box = inline_text_box->NextInlineTextBox()->NextInlineTextBox();
EXPECT_EQ("the paragraph.", inline_text_box->GetText());
EXPECT_EQ(58u, inline_text_box->TextOffsetInFormattingContext(0u));
// Ensure that calling TextOffsetInFormattingContext on a br gives the correct
// result.
const Element& br_element = *GetDocument().getElementById("br");
auto& br_text = *To<LayoutText>(br_element.GetLayoutObject());
inline_text_box = br_text.FirstAbstractInlineTextBox();
EXPECT_EQ("\n", inline_text_box->GetText());
EXPECT_EQ(0u, inline_text_box->TextOffsetInFormattingContext(0));
}
TEST_P(AbstractInlineTextBoxTest, CharacterWidths) {
// There should be a line break at the space after "012".
SetBodyInnerHTML(R"HTML(
<style>* { font-size: 10px; }</style>
<div id="div" style="width: 0ch">012 345</div>)HTML");
const Element& div = *GetDocument().getElementById("div");
auto& layout_text = *To<LayoutText>(div.firstChild()->GetLayoutObject());
scoped_refptr<AbstractInlineTextBox> inline_text_box =
layout_text.FirstAbstractInlineTextBox();
Vector<float> widths;
inline_text_box->CharacterWidths(widths);
// There should be four elements in the "widths" vector, not three, because
// the width of the trailing space should be included.
EXPECT_EQ(4u, widths.size());
EXPECT_TRUE(inline_text_box->NeedsTrailingSpace());
}
} // namespace blink