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

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: 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 "core/dom/Document.h"
9 #include "core/dom/Element.h"
10 #include "core/dom/ElementRegistrationOptions.h"
11 #include "core/dom/custom/CustomElementDefinition.h"
12 #include "core/dom/custom/CustomElementDefinitionBuilder.h"
13 #include "core/dom/custom/CustomElementDescriptor.h"
14 #include "core/dom/custom/CustomElementTestHelpers.h"
15 #include "core/dom/shadow/ShadowRoot.h"
16 #include "core/dom/shadow/ShadowRootInit.h"
17 #include "core/html/HTMLDocument.h"
18 #include "core/testing/DummyPageHolder.h"
19 #include "platform/ScriptForbiddenScope.h"
20 #include "platform/heap/Handle.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "wtf/OwnPtr.h"
23 #include "wtf/text/AtomicString.h"
24
25 namespace blink {
26
27 class CustomElementsRegistryTestBase : public ::testing::Test {
28 public:
yosin_UTC9 2016/06/01 06:15:45 No need to have public accessibility for Test clas
dominicc (has gone to gerrit) 2016/06/01 23:30:57 I suspect you're wrong about this; fixtures using
yosin_UTC9 2016/06/02 02:02:18 Sorry, my explanation is bad. I mean all members o
29 virtual Document& document() = 0;
30 virtual CustomElementsRegistry& registry() = 0;
31
32 void collectCandidates(
33 const CustomElementDescriptor& desc,
34 HeapVector<Member<Element>>* elements)
35 {
36 registry().collectCandidates(desc, elements);
37 }
38 };
39
40 class CustomElementsRegistryTest : public CustomElementsRegistryTestBase {
41 public:
yosin_UTC9 2016/06/01 06:15:44 No need to have public accessibility for Test clas
42 Document& document() override { return *m_document; }
43 CustomElementsRegistry& registry() override { return *m_registry; }
44
45 protected:
46 void SetUp() override
47 {
48 CustomElementsRegistryTestBase::SetUp();
49
50 m_document = HTMLDocument::create();
51 m_document->appendChild(CreateElement("html").inDocument(m_document));
52
53 m_registry = CustomElementsRegistry::create(m_document);
54 }
55
56 void TearDown() override
57 {
58 m_document = nullptr;
59 m_registry = nullptr;
60 CustomElementsRegistryTestBase::TearDown();
61 }
62
63 private:
64 Persistent<Document> m_document;
65 Persistent<CustomElementsRegistry> m_registry;
66 };
67
68 class CustomElementsRegistryFrameTest : public CustomElementsRegistryTestBase {
69 public:
yosin_UTC9 2016/06/01 06:15:45 No need to have public accessibility for Test clas
70 Document& document() override { return m_page->document(); }
71 CustomElementsRegistry& registry() override
72 {
73 return *m_page->frame().localDOMWindow()->customElements();
74 }
75 ScriptState* scriptState()
76 {
77 return ScriptState::forMainWorld(&m_page->frame());
78 }
79
80 ShadowRoot* attachShadowTo(Element* element)
81 {
82 NonThrowableExceptionState noExceptions;
83 ShadowRootInit shadowRootInit;
84 return
85 element->attachShadow(scriptState(), shadowRootInit, noExceptions);
86 }
87
88 protected:
89 void SetUp() override
90 {
91 CustomElementsRegistryTestBase::SetUp();
92 m_page = DummyPageHolder::create(IntSize(1, 1));
93 }
94
95 void TearDown() override
96 {
97 m_page = nullptr;
98 CustomElementsRegistryTestBase::TearDown();
99 }
100
101 private:
102 OwnPtr<DummyPageHolder> m_page;
yosin_UTC9 2016/06/01 06:15:45 nit: Let's use std::unique_ptr<DummyPageHolder>
103 };
104
105 TEST_F(
106 CustomElementsRegistryTest,
107 collectCandidates_shouldNotIncludeElementsRemovedFromDocument)
108 {
109 Element* element = CreateElement("a-a").inDocument(&document());
110 registry().addCandidate(element);
111
112 HeapVector<Member<Element>> elements;
113 collectCandidates(
114 CustomElementDescriptor("a-a", "a-a"),
115 &elements);
116
117 EXPECT_EQ(0u, elements.size())
yosin_UTC9 2016/06/01 06:15:45 nit: isEmpty() is more readable.
dominicc (has gone to gerrit) 2016/06/01 23:30:57 True; this produces a more useful failure. With is
yosin_UTC9 2016/06/02 02:02:18 How about: EXPECT_TRUE(elements.isEmpty()) << "no
118 << "no candidates should have been found";
119 EXPECT_FALSE(elements.contains(element))
120 << "the out-of-document candidate should not have been found";
121 }
122
123 TEST_F(
124 CustomElementsRegistryTest,
125 collectCandidates_shouldNotIncludeElementsInDifferentDocument)
126 {
127 Element* element = CreateElement("a-a").inDocument(&document());
128 registry().addCandidate(element);
129
130 Document* otherDocument = HTMLDocument::create();
131 otherDocument->appendChild(element);
132 EXPECT_EQ(otherDocument, element->ownerDocument())
133 << "sanity: another document should have adopted an element on append";
134
135 HeapVector<Member<Element>> elements;
136 collectCandidates(
137 CustomElementDescriptor("a-a", "a-a"),
138 &elements);
139
140 EXPECT_EQ(0u, elements.size())
141 << "no candidates should have been found";
142 EXPECT_FALSE(elements.contains(element))
143 << "the adopted-away candidate should not have been found";
144 }
145
146 TEST_F(
147 CustomElementsRegistryTest,
148 collectCandidates_shouldOnlyIncludeCandidatesMatchingDescriptor)
149 {
150 CustomElementDescriptor descriptor("hello-world", "hello-world");
151
152 // Does not match: namespace is not HTML
153 Element* a = CreateElement("hello-world")
yosin_UTC9 2016/06/01 06:15:45 Please avoid to use one letter variable name.
154 .inDocument(&document())
155 .inNamespace("data:text/date,1981-03-10");
156 // Matches
157 Element* b = CreateElement("hello-world").inDocument(&document());
158 // Does not match: local name is not hello-world
159 Element* c = CreateElement("button")
160 .inDocument(&document())
161 .withIsAttribute("hello-world");
162 document().documentElement()->appendChild(a);
163 a->appendChild(b);
164 a->appendChild(c);
165
166 registry().addCandidate(a);
167 registry().addCandidate(b);
168 registry().addCandidate(c);
169
170 HeapVector<Member<Element>> elements;
171 collectCandidates(descriptor, &elements);
172
173 EXPECT_EQ(1u, elements.size())
174 << "only one candidates should have been found";
175 EXPECT_EQ(b, elements[0])
176 << "the matching element should have been found";
177 }
178
179 TEST_F(CustomElementsRegistryTest, collectCandidates_oneCandidate)
180 {
181 Element* element = CreateElement("a-a").inDocument(&document());
182 registry().addCandidate(element);
183 document().documentElement()->appendChild(element);
184
185 HeapVector<Member<Element>> elements;
186 collectCandidates(
187 CustomElementDescriptor("a-a", "a-a"),
188 &elements);
189
190 EXPECT_EQ(1u, elements.size())
191 << "exactly one candidate should have been found";
192 EXPECT_TRUE(elements.contains(element))
193 << "the candidate should be the element that was added";
194 }
195
196 TEST_F(CustomElementsRegistryTest, collectCandidates_shouldBeInDocumentOrder)
197 {
198 CreateElement& factory = CreateElement("a-a").inDocument(&document());
199 Element* a = factory.withId("a");
200 Element* b = factory.withId("b");
201 Element* c = factory.withId("c");
202
203 registry().addCandidate(b);
204 registry().addCandidate(a);
205 registry().addCandidate(c);
206
207 document().documentElement()->appendChild(a);
208 a->appendChild(b);
209 document().documentElement()->appendChild(c);
210
211 HeapVector<Member<Element>> elements;
212 collectCandidates(
213 CustomElementDescriptor("a-a", "a-a"),
214 &elements);
215
216 EXPECT_EQ(a, elements[0].get());
217 EXPECT_EQ(b, elements[1].get());
218 EXPECT_EQ(c, elements[2].get());
219 }
220
221 class TestCustomElementDefinition : public CustomElementDefinition {
222 WTF_MAKE_NONCOPYABLE(TestCustomElementDefinition);
223 public:
224 TestCustomElementDefinition(const CustomElementDescriptor& descriptor)
225 : CustomElementDefinition(descriptor)
226 {
227 }
228
229 virtual ~TestCustomElementDefinition() = default;
230
231 bool runConstructor(Element* element) override
232 {
233 if (constructionStack().isEmpty()
234 || constructionStack().last() != element)
235 return false;
236 constructionStack().last().clear();
237 return true;
238 }
239 };
240
241 // Classes which use trace macros cannot be local because of the
242 // traceImpl template.
243 class LogUpgradeDefinition : public TestCustomElementDefinition {
244 WTF_MAKE_NONCOPYABLE(LogUpgradeDefinition);
245 public:
246 LogUpgradeDefinition(const CustomElementDescriptor& descriptor)
247 : TestCustomElementDefinition(descriptor)
248 {
249 }
250
251 DEFINE_INLINE_VIRTUAL_TRACE()
252 {
253 TestCustomElementDefinition::trace(visitor);
254 visitor->trace(m_element);
255 }
256
257 // TODO(dominicc): Make this class collect a vector of what's
258 // upgraded; it will be useful in more tests.
259 Member<Element> m_element;
260 uint32_t m_invocationCount;
261
262 bool runConstructor(Element* element) override
263 {
264 m_invocationCount++;
265 m_element = element;
266 return TestCustomElementDefinition::runConstructor(element);
267 }
268 };
269
270 class LogUpgradeBuilder final : public CustomElementDefinitionBuilder {
271 STACK_ALLOCATED();
272 WTF_MAKE_NONCOPYABLE(LogUpgradeBuilder);
273 public:
274 LogUpgradeBuilder() { }
275
276 bool checkConstructorIntrinsics() override { return true; }
277 bool checkConstructorNotRegistered() override { return true; }
278 bool checkPrototype() override { return true; }
279 CustomElementDefinition* build(
280 const CustomElementDescriptor& descriptor) {
281 return new LogUpgradeDefinition(descriptor);
282 }
283 };
284
285 TEST_F(CustomElementsRegistryFrameTest, define_upgradesInDocumentElements)
286 {
287 ScriptForbiddenScope doNotRelyOnScript;
288
289 Element* element = CreateElement("a-a").inDocument(&document());
290 document().documentElement()->appendChild(element);
291
292 LogUpgradeBuilder builder;
293 NonThrowableExceptionState shouldNotThrow;
294 registry().define(
295 "a-a",
296 builder,
297 ElementRegistrationOptions(),
298 shouldNotThrow);
299 LogUpgradeDefinition* definition =
300 static_cast<LogUpgradeDefinition*>(registry().definitionForName("a-a"));
301 EXPECT_EQ(1u, definition->m_invocationCount)
302 << "defining the element should have 'upgraded' the existing element";
303 EXPECT_EQ(element, definition->m_element)
304 << "the existing a-a element should have been upgraded";
305 }
306
307 // TODO(dominicc): Add tests which adjust the "is" attribute when type
308 // extensions are implemented.
309
310 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698