OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 "config.h" | |
6 #include "HTMLNames.h" | |
7 #include "core/dom/Element.h" | |
8 #include "core/dom/ElementTraversal.h" | |
9 #include "core/frame/FrameView.h" | |
10 #include "core/html/HTMLDocument.h" | |
11 #include "core/html/HTMLElement.h" | |
12 #include "core/testing/DummyPageHolder.h" | |
13 #include <gtest/gtest.h> | |
14 | |
15 using namespace WebCore; | |
16 using namespace HTMLNames; | |
17 | |
18 namespace { | |
19 | |
20 class AffectedByFocusTest : public ::testing::Test { | |
eseidel
2014/01/31 06:25:19
Very cool that we're building up more unittest arc
| |
21 | |
22 protected: | |
23 | |
24 struct ElementResult { | |
25 const WebCore::QualifiedName tag; | |
26 bool affectedBy; | |
27 bool childrenAffectedBy; | |
28 }; | |
29 | |
30 virtual void SetUp() OVERRIDE; | |
31 | |
32 HTMLDocument& document() const { return *m_document; } | |
33 | |
34 void setHtmlInnerHTML(const char* htmlContent); | |
35 | |
36 void checkElements(ElementResult expected[], unsigned expectedCount) const; | |
37 | |
38 private: | |
39 OwnPtr<DummyPageHolder> m_dummyPageHolder; | |
40 | |
41 HTMLDocument* m_document; | |
42 }; | |
43 | |
44 void AffectedByFocusTest::SetUp() | |
45 { | |
46 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); | |
47 m_document = toHTMLDocument(&m_dummyPageHolder->document()); | |
48 ASSERT(m_document); | |
49 } | |
50 | |
51 void AffectedByFocusTest::setHtmlInnerHTML(const char* htmlContent) | |
52 { | |
53 document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent), AS SERT_NO_EXCEPTION); | |
54 document().view()->updateLayoutAndStyleIfNeededRecursive(); | |
55 } | |
56 | |
57 void AffectedByFocusTest::checkElements(ElementResult expected[], unsigned expec tedCount) const | |
58 { | |
59 unsigned i = 0; | |
60 Element* elm = document().body(); | |
61 | |
62 for (; elm && i < 5; elm = ElementTraversal::next(*elm), ++i) { | |
63 ASSERT_TRUE(elm->hasTagName(expected[i].tag)); | |
64 ASSERT(elm->renderStyle()); | |
65 ASSERT_EQ(expected[i].affectedBy, elm->renderStyle()->affectedByFocus()) ; | |
66 ASSERT_EQ(expected[i].childrenAffectedBy, elm->childrenAffectedByFocus() ); | |
67 } | |
68 | |
69 ASSERT(!elm && i == size); | |
70 } | |
71 | |
72 // A global :focus rule in html.css currently causes every single element to be | |
eseidel
2014/01/31 06:25:19
We have a bug open with the w3c about this: https
| |
73 // affectedByFocus. Check that all elements in a document with no :focus rules | |
74 // gets the affectedByFocus set on RenderStyle and not childrenAffectedByFocus. | |
75 TEST_F(AffectedByFocusTest, UAUniversalFocusRule) | |
76 { | |
77 ElementResult expected[] = { | |
78 { bodyTag, true, false }, | |
79 { divTag, true, false }, | |
80 { divTag, true, false }, | |
81 { divTag, true, false }, | |
82 { spanTag, true, false } | |
83 }; | |
84 | |
85 setHtmlInnerHTML("<body>" | |
86 "<div><div></div></div>" | |
87 "<div><span></span></div>" | |
88 "</body>"); | |
89 | |
90 checkElements(expected, sizeof(expected) / sizeof(ElementResult)); | |
91 } | |
92 | |
93 // ":focus div" will mark ascendants of all divs with childrenAffectedByFocus. | |
94 TEST_F(AffectedByFocusTest, FocusedAscendant) | |
95 { | |
96 ElementResult expected[] = { | |
97 { bodyTag, true, true }, | |
98 { divTag, true, true }, | |
99 { divTag, true, false }, | |
100 { divTag, true, false }, | |
101 { spanTag, true, false } | |
102 }; | |
103 | |
104 setHtmlInnerHTML("<head>" | |
105 "<style>:focus div { background-color: pink }</style>" | |
106 "</head>" | |
107 "<body>" | |
108 "<div><div></div></div>" | |
109 "<div><span></span></div>" | |
110 "</body>"); | |
111 | |
112 checkElements(expected, sizeof(expected) / sizeof(ElementResult)); | |
113 } | |
114 | |
115 // "body:focus div" will mark the body element with childrenAffectedByFocus. | |
116 TEST_F(AffectedByFocusTest, FocusedAscendantWithType) | |
117 { | |
118 ElementResult expected[] = { | |
119 { bodyTag, true, true }, | |
120 { divTag, true, false }, | |
121 { divTag, true, false }, | |
122 { divTag, true, false }, | |
123 { spanTag, true, false } | |
124 }; | |
125 | |
126 setHtmlInnerHTML("<head>" | |
127 "<style>body:focus div { background-color: pink }</style>" | |
128 "</head>" | |
129 "<body>" | |
130 "<div><div></div></div>" | |
131 "<div><span></span></div>" | |
132 "</body>"); | |
133 | |
134 checkElements(expected, sizeof(expected) / sizeof(ElementResult)); | |
135 } | |
136 | |
137 // ":not(body):focus div" should not mark the body element with childrenAffected ByFocus. | |
138 // Note that currently ":focus:not(body)" does not do the same. Then the :focus is | |
139 // checked and the childrenAffectedByFocus flag set before the negated type sele ctor | |
140 // is found. | |
141 TEST_F(AffectedByFocusTest, FocusedAscendantWithNegatedType) | |
142 { | |
143 ElementResult expected[] = { | |
144 { bodyTag, true, false }, | |
145 { divTag, true, true }, | |
146 { divTag, true, false }, | |
147 { divTag, true, false }, | |
148 { spanTag, true, false } | |
149 }; | |
150 | |
151 setHtmlInnerHTML("<head>" | |
152 "<style>:not(body):focus div { background-color: pink }</style>" | |
153 "</head>" | |
154 "<body>" | |
155 "<div><div></div></div>" | |
156 "<div><span></span></div>" | |
157 "</body>"); | |
158 | |
159 checkElements(expected, sizeof(expected) / sizeof(ElementResult)); | |
160 } | |
161 | |
162 // Checking current behavior for ":focus + div", but this is a BUG or at best | |
163 // sub-optimal. The focused element will also in this case get childrenAffectedB yFocus | |
164 // even if it's really a sibling. Effectively, the whole sub-tree of the focused | |
165 // element will have styles recalculated even though none of the children are | |
166 // affected. There are other mechanisms that makes sure the sibling also gets it s | |
167 // styles recalculated. | |
168 TEST_F(AffectedByFocusTest, FocusedSibling) | |
169 { | |
170 ElementResult expected[] = { | |
171 { bodyTag, true, false }, | |
172 { divTag, true, true }, | |
173 { spanTag, true, false }, | |
174 { divTag, true, false } | |
175 }; | |
176 | |
177 setHtmlInnerHTML("<head>" | |
178 "<style>:focus + div { background-color: pink }</style>" | |
179 "</head>" | |
180 "<body>" | |
181 "<div>" | |
182 " <span></span>" | |
183 "</div>" | |
184 "<div></div>" | |
185 "</body>"); | |
186 | |
187 checkElements(expected, sizeof(expected) / sizeof(ElementResult)); | |
188 } | |
189 | |
190 TEST_F(AffectedByFocusTest, AffectedByFocusUpdate) | |
191 { | |
192 // Check that when focussing the outer div in the document below, you only | |
193 // get a single element style recalc. | |
194 | |
195 setHtmlInnerHTML("<style>:focus { border: 1px solid lime; }</style>" | |
196 "<div id=d tabIndex=1>" | |
197 "<div></div>" | |
198 "<div></div>" | |
199 "<div></div>" | |
200 "<div></div>" | |
201 "<div></div>" | |
202 "<div></div>" | |
203 "<div></div>" | |
204 "<div></div>" | |
205 "<div></div>" | |
206 "<div></div>" | |
207 "</div>"); | |
208 | |
209 document().view()->updateLayoutAndStyleIfNeededRecursive(); | |
210 | |
211 unsigned startCount = document().styleEngine()->resolverAccessCount(); | |
212 | |
213 document().getElementById("d")->focus(); | |
214 document().view()->updateLayoutAndStyleIfNeededRecursive(); | |
215 | |
216 unsigned accessCount = document().styleEngine()->resolverAccessCount() - sta rtCount; | |
217 | |
218 ASSERT_EQ(1U, accessCount); | |
219 } | |
220 | |
221 TEST_F(AffectedByFocusTest, ChildrenAffectedByFocusUpdate) | |
222 { | |
223 // Check that when focussing the outer div in the document below, you get a | |
224 // style recalc for the whole subtree. | |
225 | |
226 setHtmlInnerHTML("<style>:focus div { border: 1px solid lime; }</style>" | |
227 "<div id=d tabIndex=1>" | |
228 "<div></div>" | |
229 "<div></div>" | |
230 "<div></div>" | |
231 "<div></div>" | |
232 "<div></div>" | |
233 "<div></div>" | |
234 "<div></div>" | |
235 "<div></div>" | |
236 "<div></div>" | |
237 "<div></div>" | |
238 "</div>"); | |
239 | |
240 document().view()->updateLayoutAndStyleIfNeededRecursive(); | |
241 | |
242 unsigned startCount = document().styleEngine()->resolverAccessCount(); | |
243 | |
244 document().getElementById("d")->focus(); | |
245 document().view()->updateLayoutAndStyleIfNeededRecursive(); | |
246 | |
247 unsigned accessCount = document().styleEngine()->resolverAccessCount() - sta rtCount; | |
248 | |
249 ASSERT_EQ(11U, accessCount); | |
250 } | |
251 | |
252 } // namespace | |
OLD | NEW |