blob: 1aa2ae7778ce993a03d11a06767e7cf7a5831130 [file] [log] [blame]
// 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 "core/layout/ng/inline/ng_inline_fragment_traversal.h"
#include "core/layout/ng/inline/ng_physical_text_fragment.h"
#include "core/layout/ng/ng_layout_test.h"
#include "core/layout/ng/ng_physical_box_fragment.h"
namespace blink {
class NGInlineFragmentTraversalTest
: public NGLayoutTest,
private ScopedLayoutNGPaintFragmentsForTest {
public:
NGInlineFragmentTraversalTest()
: NGLayoutTest(), ScopedLayoutNGPaintFragmentsForTest(true) {}
protected:
const NGPhysicalBoxFragment& GetRootFragmentById(const char* id) const {
const Element* element = GetElementById(id);
DCHECK(element) << id;
const LayoutObject* layout_object = element->GetLayoutObject();
DCHECK(layout_object) << element;
DCHECK(layout_object->IsLayoutBlockFlow()) << element;
DCHECK(ToLayoutBlockFlow(layout_object)->CurrentFragment()) << element;
return *ToLayoutBlockFlow(layout_object)->CurrentFragment();
}
const NGPhysicalFragment& GetFragmentOfNode(
const NGPhysicalContainerFragment& container,
const Node* node) const {
const LayoutObject* layout_object = node->GetLayoutObject();
auto fragments =
NGInlineFragmentTraversal::SelfFragmentsOf(container, layout_object);
return *fragments.front().fragment;
}
};
#define EXPECT_NEXT_BOX(iter, id) \
{ \
const auto& current = *iter++; \
EXPECT_TRUE(current.fragment->IsBox()) << current.fragment->ToString(); \
EXPECT_EQ(GetLayoutObjectByElementId(id), \
current.fragment->GetLayoutObject()); \
}
#define EXPECT_NEXT_LINE_BOX(iter) \
{ \
const auto& current = *iter++; \
EXPECT_TRUE(current.fragment->IsLineBox()) \
<< current.fragment->ToString(); \
}
#define EXPECT_NEXT_TEXT(iter, content) \
{ \
const auto& current = *iter++; \
EXPECT_TRUE(current.fragment->IsText()) << current.fragment->ToString(); \
EXPECT_EQ(content, \
ToNGPhysicalTextFragment(current.fragment.get())->Text()); \
}
TEST_F(NGInlineFragmentTraversalTest, DescendantsOf) {
SetBodyInnerHTML(
"<style>* { border: 1px solid}</style>"
"<div id=t>foo<b id=b>bar</b><br>baz</div>");
const auto descendants =
NGInlineFragmentTraversal::DescendantsOf(GetRootFragmentById("t"));
auto iter = descendants.begin();
EXPECT_NEXT_LINE_BOX(iter);
EXPECT_NEXT_TEXT(iter, "foo");
EXPECT_NEXT_BOX(iter, "b");
EXPECT_NEXT_TEXT(iter, "bar");
EXPECT_NEXT_TEXT(iter, "\n");
EXPECT_NEXT_LINE_BOX(iter);
EXPECT_NEXT_TEXT(iter, "baz");
EXPECT_EQ(iter, descendants.end());
}
TEST_F(NGInlineFragmentTraversalTest, InclusiveDescendantsOf) {
SetBodyInnerHTML(
"<style>* { border: 1px solid}</style>"
"<div id=t>foo<b id=b>bar</b><br>baz</div>");
auto descendants = NGInlineFragmentTraversal::InclusiveDescendantsOf(
GetRootFragmentById("t"));
auto iter = descendants.begin();
EXPECT_NEXT_BOX(iter, "t");
EXPECT_NEXT_LINE_BOX(iter);
EXPECT_NEXT_TEXT(iter, "foo");
EXPECT_NEXT_BOX(iter, "b");
EXPECT_NEXT_TEXT(iter, "bar");
EXPECT_NEXT_TEXT(iter, "\n");
EXPECT_NEXT_LINE_BOX(iter);
EXPECT_NEXT_TEXT(iter, "baz");
EXPECT_EQ(iter, descendants.end());
}
TEST_F(NGInlineFragmentTraversalTest, SelfFragmentsOf) {
SetBodyInnerHTML(
"<style>* { border: 1px solid}</style>"
"<div id=t>foo<b id=filter>bar<br>baz</b>bla</div>");
const auto descendants = NGInlineFragmentTraversal::SelfFragmentsOf(
GetRootFragmentById("t"), GetLayoutObjectByElementId("filter"));
auto iter = descendants.begin();
// <b> generates two box fragments since its content is in two lines.
EXPECT_NEXT_BOX(iter, "filter");
EXPECT_NEXT_TEXT(iter, "bar");
EXPECT_NEXT_TEXT(iter, "\n");
EXPECT_NEXT_BOX(iter, "filter");
EXPECT_NEXT_TEXT(iter, "baz");
EXPECT_EQ(iter, descendants.end());
}
TEST_F(NGInlineFragmentTraversalTest, AncestorsOf) {
SetBodyInnerHTML(
"<style>* { border: 1px solid}</style>"
"<div id=t>x"
"<b id=b>y<i id=i>z<u id=target>foo</u>z</i>y</b>"
"x</div>");
const NGPhysicalContainerFragment& root = GetRootFragmentById("t");
const NGPhysicalFragment& target =
GetFragmentOfNode(root, GetElementById("target")->firstChild());
auto ancestors = NGInlineFragmentTraversal::AncestorsOf(root, target);
auto iter = ancestors.begin();
EXPECT_NEXT_BOX(iter, "target");
EXPECT_NEXT_BOX(iter, "i");
EXPECT_NEXT_BOX(iter, "b");
EXPECT_NEXT_LINE_BOX(iter);
EXPECT_EQ(iter, ancestors.end());
}
TEST_F(NGInlineFragmentTraversalTest, InclusiveAncestorsOf) {
SetBodyInnerHTML(
"<style>* { border: 1px solid}</style>"
"<div id=t>x"
"<b id=b>y<i id=i>z<u id=target>foo</u>z</i>y</b>"
"x</div>");
const NGPhysicalContainerFragment& root = GetRootFragmentById("t");
const NGPhysicalFragment& target =
GetFragmentOfNode(root, GetElementById("target")->firstChild());
auto ancestors =
NGInlineFragmentTraversal::InclusiveAncestorsOf(root, target);
auto iter = ancestors.begin();
EXPECT_NEXT_TEXT(iter, "foo");
EXPECT_NEXT_BOX(iter, "target");
EXPECT_NEXT_BOX(iter, "i");
EXPECT_NEXT_BOX(iter, "b");
EXPECT_NEXT_LINE_BOX(iter);
EXPECT_EQ(iter, ancestors.end());
}
} // namespace blink