blob: df99e4679f35ceaf9d50f4a534aee55090d82d4b [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 "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/shadow_root_v0.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
namespace blink {
namespace {
bool HasSelectorForIdInShadow(Element* host, const AtomicString& id) {
DCHECK(host);
return host->GetShadowRoot()->V0().EnsureSelectFeatureSet().HasSelectorForId(
id);
}
bool HasSelectorForClassInShadow(Element* host,
const AtomicString& class_name) {
DCHECK(host);
return host->GetShadowRoot()
->V0()
.EnsureSelectFeatureSet()
.HasSelectorForClass(class_name);
}
bool HasSelectorForAttributeInShadow(Element* host,
const AtomicString& attribute_name) {
DCHECK(host);
return host->GetShadowRoot()
->V0()
.EnsureSelectFeatureSet()
.HasSelectorForAttribute(attribute_name);
}
class ShadowDOMV0Test : public SimTest {};
TEST_F(ShadowDOMV0Test, FeatureSetId) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
auto* content = GetDocument().CreateRawElement(html_names::kContentTag);
content->setAttribute("select", "#foo");
host->CreateV0ShadowRootForTesting().AppendChild(content);
EXPECT_TRUE(HasSelectorForIdInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "host"));
content->setAttribute("select", "#bar");
EXPECT_TRUE(HasSelectorForIdInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "foo"));
content->setAttribute("select", "");
EXPECT_FALSE(HasSelectorForIdInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "foo"));
}
TEST_F(ShadowDOMV0Test, FeatureSetClassName) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
auto* content = GetDocument().CreateRawElement(html_names::kContentTag);
content->setAttribute("select", ".foo");
host->CreateV0ShadowRootForTesting().AppendChild(content);
EXPECT_TRUE(HasSelectorForClassInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "host"));
content->setAttribute("select", ".bar");
EXPECT_TRUE(HasSelectorForClassInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "foo"));
content->setAttribute("select", "");
EXPECT_FALSE(HasSelectorForClassInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "foo"));
}
TEST_F(ShadowDOMV0Test, FeatureSetAttributeName) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
auto* content = GetDocument().CreateRawElement(html_names::kContentTag);
content->setAttribute("select", "div[foo]");
host->CreateV0ShadowRootForTesting().AppendChild(content);
EXPECT_TRUE(HasSelectorForAttributeInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "host"));
content->setAttribute("select", "div[bar]");
EXPECT_TRUE(HasSelectorForAttributeInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "foo"));
content->setAttribute("select", "");
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "foo"));
}
TEST_F(ShadowDOMV0Test, FeatureSetMultipleSelectors) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
auto* content = GetDocument().CreateRawElement(html_names::kContentTag);
content->setAttribute("select", "#foo,.bar,div[baz]");
host->CreateV0ShadowRootForTesting().AppendChild(content);
EXPECT_TRUE(HasSelectorForIdInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "baz"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "foo"));
EXPECT_TRUE(HasSelectorForClassInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "baz"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "bar"));
EXPECT_TRUE(HasSelectorForAttributeInShadow(host, "baz"));
}
TEST_F(ShadowDOMV0Test, FeatureSetSubtree) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
host->CreateV0ShadowRootForTesting().SetInnerHTMLFromString(R"HTML(
<div>
<div></div>
<content select='*'></content>
<div>
<content select='div[foo=piyo]'></content>
</div>
</div>
)HTML");
EXPECT_FALSE(HasSelectorForIdInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForClassInShadow(host, "foo"));
EXPECT_TRUE(HasSelectorForAttributeInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForAttributeInShadow(host, "piyo"));
}
TEST_F(ShadowDOMV0Test, FeatureSetMultipleShadowRoots) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
auto& host_shadow = host->CreateV0ShadowRootForTesting();
host_shadow.SetInnerHTMLFromString("<content select='#foo'></content>");
auto* child = GetDocument().CreateRawElement(html_names::kDivTag);
auto& child_root = child->CreateV0ShadowRootForTesting();
auto* child_content = GetDocument().CreateRawElement(html_names::kContentTag);
child_content->setAttribute("select", "#bar");
child_root.AppendChild(child_content);
host_shadow.AppendChild(child);
EXPECT_TRUE(HasSelectorForIdInShadow(host, "foo"));
EXPECT_TRUE(HasSelectorForIdInShadow(host, "bar"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "baz"));
child_content->setAttribute("select", "#baz");
EXPECT_TRUE(HasSelectorForIdInShadow(host, "foo"));
EXPECT_FALSE(HasSelectorForIdInShadow(host, "bar"));
EXPECT_TRUE(HasSelectorForIdInShadow(host, "baz"));
}
TEST_F(ShadowDOMV0Test, ReattachNonDistributedElements) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
auto* inner_host = GetDocument().CreateRawElement(html_names::kDivTag);
auto* span = GetDocument().CreateRawElement(html_names::kSpanTag);
GetDocument().body()->appendChild(host);
host->appendChild(inner_host);
inner_host->appendChild(span);
GetDocument().View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
host->CreateV0ShadowRootForTesting();
inner_host->CreateV0ShadowRootForTesting();
inner_host->SetInlineStyleProperty(CSSPropertyID::kDisplay,
CSSValueID::kInlineBlock);
span->SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kBlock);
GetDocument().View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_FALSE(span->NeedsReattachLayoutTree());
}
TEST_F(ShadowDOMV0Test, DetachLayoutTreeOnShadowRootCreation) {
LoadURL("about:blank");
auto* host = GetDocument().CreateRawElement(html_names::kDivTag);
host->SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kContents);
auto* span = GetDocument().CreateRawElement(html_names::kSpanTag);
host->appendChild(span);
GetDocument().body()->appendChild(host);
GetDocument().View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_TRUE(span->GetLayoutObject());
host->CreateV0ShadowRootForTesting();
EXPECT_FALSE(span->GetLayoutObject());
}
} // namespace
} // namespace blink