Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: third_party/WebKit/Source/core/dom/custom/CustomElementsRegistryTest.cpp

Issue 2023093003: Upgrade in-document custom elements when an element is defined. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix ASAN failure in test helper. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/dom/custom/CustomElementsRegistry.h"
6
7 #include "bindings/core/v8/ExceptionState.h"
8 #include "bindings/core/v8/ScriptValue.h"
9 #include "core/dom/Document.h"
10 #include "core/dom/Element.h"
11 #include "core/dom/ElementRegistrationOptions.h"
12 #include "core/dom/custom/CustomElementDefinition.h"
13 #include "core/dom/custom/CustomElementDefinitionBuilder.h"
14 #include "core/dom/custom/CustomElementDescriptor.h"
15 #include "core/dom/custom/CustomElementTestHelpers.h"
16 #include "core/dom/shadow/ShadowRoot.h"
17 #include "core/dom/shadow/ShadowRootInit.h"
18 #include "core/html/HTMLDocument.h"
19 #include "core/testing/DummyPageHolder.h"
20 #include "platform/ScriptForbiddenScope.h"
21 #include "platform/heap/Handle.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "wtf/text/AtomicString.h"
24 #include <memory>
25
26 namespace blink {
27
28 class CustomElementsRegistryTestBase : public ::testing::Test {
29 protected:
30 virtual Document& document() = 0;
31 virtual CustomElementsRegistry& registry() = 0;
32
33 void collectCandidates(
34 const CustomElementDescriptor& desc,
35 HeapVector<Member<Element>>* elements)
36 {
37 registry().collectCandidates(desc, elements);
38 }
39 };
40
41 class CustomElementsRegistryTest : public CustomElementsRegistryTestBase {
42 protected:
43 void SetUp() override
44 {
45 CustomElementsRegistryTestBase::SetUp();
46
47 m_document = HTMLDocument::create();
48 m_document->appendChild(CreateElement("html").inDocument(m_document));
49
50 m_registry = CustomElementsRegistry::create(m_document);
51 }
52
53 void TearDown() override
54 {
55 m_document = nullptr;
56 m_registry = nullptr;
57 CustomElementsRegistryTestBase::TearDown();
58 }
59
60 Document& document() override { return *m_document; }
61 CustomElementsRegistry& registry() override { return *m_registry; }
62
63 private:
64 Persistent<Document> m_document;
65 Persistent<CustomElementsRegistry> m_registry;
66 };
67
68 class CustomElementsRegistryFrameTest : public CustomElementsRegistryTestBase {
69 protected:
70 void SetUp() override
71 {
72 CustomElementsRegistryTestBase::SetUp();
73 m_page.reset(DummyPageHolder::create(IntSize(1, 1)).leakPtr());
74 }
75
76 void TearDown() override
77 {
78 m_page = nullptr;
79 CustomElementsRegistryTestBase::TearDown();
80 }
81
82 Document& document() override { return m_page->document(); }
83
84 CustomElementsRegistry& registry() override
85 {
86 return *m_page->frame().localDOMWindow()->customElements();
87 }
88
89 ScriptState* scriptState()
90 {
91 return ScriptState::forMainWorld(&m_page->frame());
92 }
93
94 ShadowRoot* attachShadowTo(Element* element)
95 {
96 NonThrowableExceptionState noExceptions;
97 ShadowRootInit shadowRootInit;
98 return
99 element->attachShadow(scriptState(), shadowRootInit, noExceptions);
100 }
101
102 private:
103 std::unique_ptr<DummyPageHolder> m_page;
104 };
105
106 TEST_F(
107 CustomElementsRegistryTest,
108 collectCandidates_shouldNotIncludeElementsRemovedFromDocument)
109 {
110 Element* element = CreateElement("a-a").inDocument(&document());
111 registry().addCandidate(element);
112
113 HeapVector<Member<Element>> elements;
114 collectCandidates(
115 CustomElementDescriptor("a-a", "a-a"),
116 &elements);
117
118 EXPECT_TRUE(elements.isEmpty())
119 << "no candidates should have been found, but we have "
120 << elements.size();
121 EXPECT_FALSE(elements.contains(element))
122 << "the out-of-document candidate should not have been found";
123 }
124
125 TEST_F(
126 CustomElementsRegistryTest,
127 collectCandidates_shouldNotIncludeElementsInDifferentDocument)
128 {
129 Element* element = CreateElement("a-a").inDocument(&document());
130 registry().addCandidate(element);
131
132 Document* otherDocument = HTMLDocument::create();
133 otherDocument->appendChild(element);
134 EXPECT_EQ(otherDocument, element->ownerDocument())
135 << "sanity: another document should have adopted an element on append";
136
137 HeapVector<Member<Element>> elements;
138 collectCandidates(
139 CustomElementDescriptor("a-a", "a-a"),
140 &elements);
141
142 EXPECT_TRUE(elements.isEmpty())
143 << "no candidates should have been found, but we have "
144 << elements.size();
145 EXPECT_FALSE(elements.contains(element))
146 << "the adopted-away candidate should not have been found";
147 }
148
149 TEST_F(
150 CustomElementsRegistryTest,
151 collectCandidates_shouldOnlyIncludeCandidatesMatchingDescriptor)
152 {
153 CustomElementDescriptor descriptor("hello-world", "hello-world");
154
155 // Does not match: namespace is not HTML
156 Element* elementA = CreateElement("hello-world")
157 .inDocument(&document())
158 .inNamespace("data:text/date,1981-03-10");
159 // Matches
160 Element* elementB = CreateElement("hello-world").inDocument(&document());
161 // Does not match: local name is not hello-world
162 Element* elementC = CreateElement("button")
163 .inDocument(&document())
164 .withIsAttribute("hello-world");
165 document().documentElement()->appendChild(elementA);
166 elementA->appendChild(elementB);
167 elementA->appendChild(elementC);
168
169 registry().addCandidate(elementA);
170 registry().addCandidate(elementB);
171 registry().addCandidate(elementC);
172
173 HeapVector<Member<Element>> elements;
174 collectCandidates(descriptor, &elements);
175
176 EXPECT_EQ(1u, elements.size())
177 << "only one candidates should have been found";
178 EXPECT_EQ(elementB, elements[0])
179 << "the matching element should have been found";
180 }
181
182 TEST_F(CustomElementsRegistryTest, collectCandidates_oneCandidate)
183 {
184 Element* element = CreateElement("a-a").inDocument(&document());
185 registry().addCandidate(element);
186 document().documentElement()->appendChild(element);
187
188 HeapVector<Member<Element>> elements;
189 collectCandidates(
190 CustomElementDescriptor("a-a", "a-a"),
191 &elements);
192
193 EXPECT_EQ(1u, elements.size())
194 << "exactly one candidate should have been found";
195 EXPECT_TRUE(elements.contains(element))
196 << "the candidate should be the element that was added";
197 }
198
199 TEST_F(CustomElementsRegistryTest, collectCandidates_shouldBeInDocumentOrder)
200 {
201 CreateElement factory = CreateElement("a-a");
202 factory.inDocument(&document());
203 Element* elementA = factory.withId("a");
204 Element* elementB = factory.withId("b");
205 Element* elementC = factory.withId("c");
206
207 registry().addCandidate(elementB);
208 registry().addCandidate(elementA);
209 registry().addCandidate(elementC);
210
211 document().documentElement()->appendChild(elementA);
212 elementA->appendChild(elementB);
213 document().documentElement()->appendChild(elementC);
214
215 HeapVector<Member<Element>> elements;
216 collectCandidates(
217 CustomElementDescriptor("a-a", "a-a"),
218 &elements);
219
220 EXPECT_EQ(elementA, elements[0].get());
221 EXPECT_EQ(elementB, elements[1].get());
222 EXPECT_EQ(elementC, elements[2].get());
223 }
224
225 class TestCustomElementDefinition : public CustomElementDefinition {
226 WTF_MAKE_NONCOPYABLE(TestCustomElementDefinition);
227 public:
228 TestCustomElementDefinition(const CustomElementDescriptor& descriptor)
229 : CustomElementDefinition(descriptor)
230 {
231 }
232
233 ~TestCustomElementDefinition() override = default;
234
235 ScriptValue getConstructorForScript() override
236 {
237 return ScriptValue();
238 }
239
240 bool runConstructor(Element* element) override
241 {
242 if (constructionStack().isEmpty()
243 || constructionStack().last() != element)
244 return false;
245 constructionStack().last().clear();
246 return true;
247 }
248 };
249
250 // Classes which use trace macros cannot be local because of the
251 // traceImpl template.
252 class LogUpgradeDefinition : public TestCustomElementDefinition {
253 WTF_MAKE_NONCOPYABLE(LogUpgradeDefinition);
254 public:
255 LogUpgradeDefinition(const CustomElementDescriptor& descriptor)
256 : TestCustomElementDefinition(descriptor)
257 {
258 }
259
260 DEFINE_INLINE_VIRTUAL_TRACE()
261 {
262 TestCustomElementDefinition::trace(visitor);
263 visitor->trace(m_element);
264 }
265
266 // TODO(dominicc): Make this class collect a vector of what's
267 // upgraded; it will be useful in more tests.
268 Member<Element> m_element;
269 uint32_t m_invocationCount;
270
271 bool runConstructor(Element* element) override
272 {
273 m_invocationCount++;
274 m_element = element;
275 return TestCustomElementDefinition::runConstructor(element);
276 }
277 };
278
279 class LogUpgradeBuilder final : public CustomElementDefinitionBuilder {
280 STACK_ALLOCATED();
281 WTF_MAKE_NONCOPYABLE(LogUpgradeBuilder);
282 public:
283 LogUpgradeBuilder() { }
284
285 bool checkConstructorIntrinsics() override { return true; }
286 bool checkConstructorNotRegistered() override { return true; }
287 bool checkPrototype() override { return true; }
288 CustomElementDefinition* build(
289 const CustomElementDescriptor& descriptor) {
290 return new LogUpgradeDefinition(descriptor);
291 }
292 };
293
294 TEST_F(CustomElementsRegistryFrameTest, define_upgradesInDocumentElements)
295 {
296 ScriptForbiddenScope doNotRelyOnScript;
297
298 Element* element = CreateElement("a-a").inDocument(&document());
299 document().documentElement()->appendChild(element);
300
301 LogUpgradeBuilder builder;
302 NonThrowableExceptionState shouldNotThrow;
303 registry().define(
304 "a-a",
305 builder,
306 ElementRegistrationOptions(),
307 shouldNotThrow);
308 LogUpgradeDefinition* definition =
309 static_cast<LogUpgradeDefinition*>(registry().definitionForName("a-a"));
310 EXPECT_EQ(1u, definition->m_invocationCount)
311 << "defining the element should have 'upgraded' the existing element";
312 EXPECT_EQ(element, definition->m_element)
313 << "the existing a-a element should have been upgraded";
314 }
315
316 // TODO(dominicc): Add tests which adjust the "is" attribute when type
317 // extensions are implemented.
318
319 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp ('k') | third_party/WebKit/Source/core/frame/FrameHost.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698