blob: ed16d8cd5f44458eed4353826adf47255b2e95e5 [file] [log] [blame]
// Copyright (c) 2016 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/dom/text.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/html/html_pre_element.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
namespace blink {
class TextTest : public EditingTestBase {};
TEST_F(TextTest, SetDataToChangeFirstLetterTextNode) {
SetBodyContent(
"<style>pre::first-letter {color:red;}</style><pre "
"id=sample>a<span>b</span></pre>");
Node* sample = GetDocument().getElementById("sample");
Text* text = ToText(sample->firstChild());
text->setData(" ");
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(text->GetLayoutObject()->IsTextFragment());
}
TEST_F(TextTest, RemoveFirstLetterPseudoElementWhenNoLetter) {
SetBodyContent("<style>*::first-letter{font:icon;}</style><pre>AB\n</pre>");
Element* pre = GetDocument().QuerySelector("pre");
Text* text = ToText(pre->firstChild());
Range* range = Range::Create(GetDocument(), text, 0, text, 2);
range->deleteContents(ASSERT_NO_EXCEPTION);
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(text->GetLayoutObject()->IsTextFragment());
}
TEST_F(TextTest, TextLayoutObjectIsNeeded_CannotHaveChildren) {
SetBodyContent("<img id=image>");
UpdateAllLifecyclePhasesForTest();
Element* img = GetDocument().getElementById("image");
ASSERT_TRUE(img);
const LayoutObject* img_layout = img->GetLayoutObject();
ASSERT_TRUE(img_layout);
const ComputedStyle& style = img_layout->StyleRef();
Text* text = Text::Create(GetDocument(), "dummy");
Node::AttachContext context;
EXPECT_FALSE(text->TextLayoutObjectIsNeeded(context, style, *img_layout));
context.use_previous_in_flow = true;
EXPECT_FALSE(text->TextLayoutObjectIsNeeded(context, style, *img_layout));
}
TEST_F(TextTest, TextLayoutObjectIsNeeded_EditingText) {
SetBodyContent("<span id=parent></span>");
UpdateAllLifecyclePhasesForTest();
Element* parent = GetDocument().getElementById("parent");
ASSERT_TRUE(parent);
const LayoutObject* parent_layout = parent->GetLayoutObject();
ASSERT_TRUE(parent_layout);
const ComputedStyle& style = parent_layout->StyleRef();
Text* text_empty = Text::CreateEditingText(GetDocument(), "");
Text* text_whitespace = Text::CreateEditingText(GetDocument(), " ");
Text* text = Text::CreateEditingText(GetDocument(), "dummy");
Node::AttachContext context;
EXPECT_TRUE(
text_empty->TextLayoutObjectIsNeeded(context, style, *parent_layout));
EXPECT_TRUE(text_whitespace->TextLayoutObjectIsNeeded(context, style,
*parent_layout));
EXPECT_TRUE(text->TextLayoutObjectIsNeeded(context, style, *parent_layout));
context.use_previous_in_flow = true;
EXPECT_TRUE(
text_empty->TextLayoutObjectIsNeeded(context, style, *parent_layout));
EXPECT_TRUE(text_whitespace->TextLayoutObjectIsNeeded(context, style,
*parent_layout));
EXPECT_TRUE(text->TextLayoutObjectIsNeeded(context, style, *parent_layout));
}
TEST_F(TextTest, TextLayoutObjectIsNeeded_Empty) {
SetBodyContent("<span id=parent></span>");
UpdateAllLifecyclePhasesForTest();
Element* parent = GetDocument().getElementById("parent");
ASSERT_TRUE(parent);
const LayoutObject* parent_layout = parent->GetLayoutObject();
ASSERT_TRUE(parent_layout);
const ComputedStyle& style = parent_layout->StyleRef();
Text* text = Text::Create(GetDocument(), "");
Node::AttachContext context;
EXPECT_FALSE(text->TextLayoutObjectIsNeeded(context, style, *parent_layout));
context.use_previous_in_flow = true;
EXPECT_FALSE(text->TextLayoutObjectIsNeeded(context, style, *parent_layout));
}
TEST_F(TextTest, TextLayoutObjectIsNeeded_Whitespace) {
SetBodyContent(
"<div id=block></div>Ends with whitespace "
"<span id=inline></span>Nospace<br id=br>");
UpdateAllLifecyclePhasesForTest();
LayoutObject* block =
GetDocument().getElementById("block")->GetLayoutObject();
LayoutObject* in_line =
GetDocument().getElementById("inline")->GetLayoutObject();
LayoutObject* space_at_end =
GetDocument().getElementById("block")->nextSibling()->GetLayoutObject();
LayoutObject* no_space =
GetDocument().getElementById("inline")->nextSibling()->GetLayoutObject();
LayoutObject* br = GetDocument().getElementById("br")->GetLayoutObject();
ASSERT_TRUE(block);
ASSERT_TRUE(in_line);
ASSERT_TRUE(space_at_end);
ASSERT_TRUE(no_space);
ASSERT_TRUE(br);
Text* whitespace = Text::Create(GetDocument(), " ");
Node::AttachContext context;
EXPECT_FALSE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_FALSE(whitespace->TextLayoutObjectIsNeeded(
context, in_line->StyleRef(), *in_line));
context.use_previous_in_flow = true;
EXPECT_FALSE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_TRUE(whitespace->TextLayoutObjectIsNeeded(context, in_line->StyleRef(),
*in_line));
context.previous_in_flow = in_line;
EXPECT_TRUE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_TRUE(whitespace->TextLayoutObjectIsNeeded(context, in_line->StyleRef(),
*in_line));
context.previous_in_flow = space_at_end;
EXPECT_FALSE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_FALSE(whitespace->TextLayoutObjectIsNeeded(
context, in_line->StyleRef(), *in_line));
context.previous_in_flow = no_space;
EXPECT_TRUE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_TRUE(whitespace->TextLayoutObjectIsNeeded(context, in_line->StyleRef(),
*in_line));
context.previous_in_flow = block;
EXPECT_FALSE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_FALSE(whitespace->TextLayoutObjectIsNeeded(
context, in_line->StyleRef(), *in_line));
context.previous_in_flow = br;
EXPECT_FALSE(
whitespace->TextLayoutObjectIsNeeded(context, block->StyleRef(), *block));
EXPECT_FALSE(whitespace->TextLayoutObjectIsNeeded(
context, in_line->StyleRef(), *in_line));
}
TEST_F(TextTest, TextLayoutObjectIsNeeded_PreserveNewLine) {
SetBodyContent(R"HTML(
<div id=pre style='white-space:pre'></div>
<div id=pre-line style='white-space:pre-line'></div>
<div id=pre-wrap style='white-space:pre-wrap'></div>
)HTML");
UpdateAllLifecyclePhasesForTest();
Text* text = Text::Create(GetDocument(), " ");
Element* pre = GetDocument().getElementById("pre");
ASSERT_TRUE(pre);
const LayoutObject* pre_layout = pre->GetLayoutObject();
ASSERT_TRUE(pre_layout);
const ComputedStyle& pre_style = pre_layout->StyleRef();
EXPECT_TRUE(text->TextLayoutObjectIsNeeded(Node::AttachContext(), pre_style,
*pre_layout));
Element* pre_line = GetDocument().getElementById("pre-line");
ASSERT_TRUE(pre_line);
const LayoutObject* pre_line_layout = pre_line->GetLayoutObject();
ASSERT_TRUE(pre_line_layout);
const ComputedStyle& pre_line_style = pre_line_layout->StyleRef();
EXPECT_TRUE(text->TextLayoutObjectIsNeeded(Node::AttachContext(),
pre_line_style, *pre_line_layout));
Element* pre_wrap = GetDocument().getElementById("pre-wrap");
ASSERT_TRUE(pre_wrap);
const LayoutObject* pre_wrap_layout = pre_wrap->GetLayoutObject();
ASSERT_TRUE(pre_wrap_layout);
const ComputedStyle& pre_wrap_style = pre_wrap_layout->StyleRef();
EXPECT_TRUE(text->TextLayoutObjectIsNeeded(Node::AttachContext(),
pre_wrap_style, *pre_wrap_layout));
}
} // namespace blink