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

Side by Side Diff: chrome/browser/web_dev_style/css_checker_test.py

Issue 2890513003: Move chrome/browser/web_dev_style/ to tools/ to use from more places (Closed)
Patch Set: tsergeant@ review Created 3 years, 7 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 #!/usr/bin/env python
2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import css_checker
7 from os import path as os_path
8 import re
9 from sys import path as sys_path
10 import unittest
11
12 _HERE = os_path.dirname(os_path.abspath(__file__))
13 sys_path.append(os_path.join(_HERE, '..', '..', '..', 'build'))
14
15 import find_depot_tools # pylint: disable=W0611
16 from testing_support.super_mox import SuperMoxTestBase
17
18
19 class CssCheckerTest(SuperMoxTestBase):
20 def setUp(self):
21 SuperMoxTestBase.setUp(self)
22
23 self.fake_file = self.mox.CreateMockAnything()
24 # Actual calls to NewContents() and LocalPath() are defined in each test.
25 self.mox.StubOutWithMock(self.fake_file, 'LocalPath')
26 self.mox.StubOutWithMock(self.fake_file, 'NewContents')
27
28 self.input_api = self.mox.CreateMockAnything()
29 self.input_api.re = re
30 self.mox.StubOutWithMock(self.input_api, 'AffectedSourceFiles')
31 self.input_api.AffectedFiles(
32 include_deletes=False, file_filter=None).AndReturn([self.fake_file])
33
34 # Actual creations of PresubmitPromptWarning are defined in each test.
35 self.output_api = self.mox.CreateMockAnything()
36 self.mox.StubOutWithMock(self.output_api, 'PresubmitPromptWarning',
37 use_mock_anything=True)
38
39 self.output_api = self.mox.CreateMockAnything()
40 self.mox.StubOutWithMock(self.output_api, 'PresubmitNotifyResult',
41 use_mock_anything=True)
42
43 def _create_file(self, contents, filename):
44 self.fake_file_name = filename
45 self.fake_file.LocalPath().AndReturn(self.fake_file_name)
46 self.fake_file.NewContents().AndReturn(contents.splitlines())
47
48 def VerifyContentIsValid(self, contents, filename='fake.css'):
49 self._create_file(contents, filename)
50 self.mox.ReplayAll()
51 css_checker.CSSChecker(self.input_api, self.output_api).RunChecks()
52
53 def VerifyContentsProducesOutput(self, contents, output, filename='fake.css'):
54 self._create_file(contents, filename)
55 self.output_api.PresubmitPromptWarning(
56 self.fake_file_name + ':\n' + output.strip()).AndReturn(None)
57 self.mox.ReplayAll()
58 css_checker.CSSChecker(self.input_api, self.output_api).RunChecks()
59
60 def testCssAlphaWithAtBlock(self):
61 self.VerifyContentsProducesOutput("""
62 <include src="../shared/css/cr/ui/overlay.css">
63 <include src="chrome://resources/totally-cool.css" />
64
65 /* A hopefully safely ignored comment and @media statement. /**/
66 @media print {
67 div {
68 display: block;
69 color: red;
70 }
71 }
72
73 .rule {
74 z-index: 5;
75 <if expr="not is macosx">
76 background-image: url(chrome://resources/BLAH); /* TODO(dbeam): Fix this. */
77 background-color: rgb(235, 239, 249);
78 </if>
79 <if expr="is_macosx">
80 background-color: white;
81 background-image: url(chrome://resources/BLAH2);
82 </if>
83 color: black;
84 }
85
86 <if expr="is_macosx">
87 .language-options-right {
88 visibility: hidden;
89 opacity: 1; /* TODO(dbeam): Fix this. */
90 }
91 </if>""", """
92 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
93 display: block;
94 color: red;
95
96 z-index: 5;
97 color: black;""")
98
99 def testCssStringWithAt(self):
100 self.VerifyContentIsValid("""
101 #logo {
102 background-image: url(images/google_logo.png@2x);
103 }
104
105 body.alternate-logo #logo {
106 -webkit-mask-image: url(images/google_logo.png@2x);
107 background: none;
108 @apply(--some-variable);
109 }
110
111 div {
112 -webkit-margin-start: 5px;
113 }
114
115 .stuff1 {
116 }
117
118 .stuff2 {
119 }
120 """)
121
122 def testCssAlphaWithNonStandard(self):
123 self.VerifyContentsProducesOutput("""
124 div {
125 /* A hopefully safely ignored comment and @media statement. /**/
126 color: red;
127 -webkit-margin-start: 5px;
128 }""", """
129 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
130 color: red;
131 -webkit-margin-start: 5px;""")
132
133 def testCssAlphaWithLongerDashedProps(self):
134 self.VerifyContentsProducesOutput("""
135 div {
136 border-left: 5px; /* A hopefully removed comment. */
137 border: 5px solid red;
138 }""", """
139 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
140 border-left: 5px;
141 border: 5px solid red;""")
142
143 def testCssAlphaWithVariables(self):
144 self.VerifyContentIsValid("""
145 #id {
146 --zzyxx-xylophone: 3px;
147 --ignore-me: {
148 /* TODO(dbeam): fix this by creating a "sort context". If we simply strip
149 * off the mixin, the inside contents will be compared to the outside
150 * contents, which isn't what we want. */
151 visibility: hidden;
152 color: black;
153 };
154 --aardvark-animal: var(--zzyxz-xylophone);
155 }
156 """)
157
158 def testCssBracesHaveSpaceBeforeAndNothingAfter(self):
159 self.VerifyContentsProducesOutput("""
160 /* Hello! */div/* Comment here*/{
161 display: block;
162 }
163
164 blah /* hey! */
165 {
166 rule: value;
167 }
168
169 .mixed-in {
170 display: none;
171 --css-mixin: {
172 color: red;
173 }; /* This should be ignored. */
174 }
175
176 .this.is { /* allowed */
177 rule: value;
178 }""", """
179 - Start braces ({) end a selector, have a space before them and no rules after.
180 div{
181 {""")
182
183 def testCssClassesUseDashes(self):
184 self.VerifyContentsProducesOutput("""
185 .className,
186 .ClassName,
187 .class-name /* We should not catch this. */,
188 .class_name {
189 display: block;
190 }""", """
191 - Classes use .dash-form.
192 .className,
193 .ClassName,
194 .class_name {""")
195
196 def testCssCloseBraceOnNewLine(self):
197 self.VerifyContentsProducesOutput("""
198 @media { /* TODO(dbeam) Fix this case. */
199 .rule {
200 display: block;
201 }}
202
203 @-webkit-keyframe blah {
204 from { height: rotate(-10turn); }
205 100% { height: 500px; }
206 }
207
208 #id { /* $i18n{*} and $i18nRaw{*} should be ignored. */
209 rule: $i18n{someValue};
210 rule2: $i18nRaw{someValue};
211 --css-mixin: {
212 color: red;
213 };
214 }
215
216 .paper-wrapper {
217 --paper-thinger: {
218 background: blue;
219 };
220 }
221
222 #rule {
223 rule: value; }""", """
224 - Always put a rule closing brace (}) on a new line.
225 rule: value; }""")
226
227 def testCssColonsHaveSpaceAfter(self):
228 self.VerifyContentsProducesOutput("""
229 div:not(.class):not([attr=5]), /* We should not catch this. */
230 div:not(.class):not([attr]) /* Nor this. */ {
231 background: url(data:image/jpeg,asdfasdfsadf); /* Ignore this. */
232 background: -webkit-linear-gradient(left, red,
233 80% blah blee blar);
234 color: red;
235 display:block;
236 }""", """
237 - Colons (:) should have a space after them.
238 display:block;
239
240 - Don't use data URIs in source files. Use grit instead.
241 background: url(data:image/jpeg,asdfasdfsadf);""")
242
243 def testCssFavorSingleQuotes(self):
244 self.VerifyContentsProducesOutput("""
245 html[dir="rtl"] body,
246 html[dir=ltr] body /* TODO(dbeam): Require '' around rtl in future? */ {
247 font-family: "Open Sans";
248 <if expr="is_macosx">
249 blah: blee;
250 </if>
251 }""", """
252 - Use single quotes (') instead of double quotes (") in strings.
253 html[dir="rtl"] body,
254 font-family: "Open Sans";""")
255
256 def testCssHexCouldBeShorter(self):
257 self.VerifyContentsProducesOutput("""
258 #abc,
259 #abc-,
260 #abc-ghij,
261 #abcdef-,
262 #abcdef-ghij,
263 #aaaaaa,
264 #bbaacc {
265 background-color: #336699; /* Ignore short hex rule if not gray. */
266 color: #999999;
267 color: #666;
268 }""", """
269 - Use abbreviated hex (#rgb) when in form #rrggbb.
270 color: #999999; (replace with #999)
271
272 - Use rgb() over #hex when not a shade of gray (like #333).
273 background-color: #336699; (replace with rgb(51, 102, 153))""")
274
275 def testCssUseMillisecondsForSmallTimes(self):
276 self.VerifyContentsProducesOutput("""
277 .transition-0s /* This is gross but may happen. */ {
278 transform: one 0.2s;
279 transform: two .1s;
280 transform: tree 1s;
281 transform: four 300ms;
282 }""", """
283 - Use milliseconds for time measurements under 1 second.
284 transform: one 0.2s; (replace with 200ms)
285 transform: two .1s; (replace with 100ms)""")
286
287 def testCssNoDataUrisInSourceFiles(self):
288 self.VerifyContentsProducesOutput("""
289 img {
290 background: url( data:image/jpeg,4\/\/350|\/|3|2 );
291 }""", """
292 - Don't use data URIs in source files. Use grit instead.
293 background: url( data:image/jpeg,4\/\/350|\/|3|2 );""")
294
295 def testCssNoMixinShims(self):
296 self.VerifyContentsProducesOutput("""
297 :host {
298 --good-property: red;
299 --not-okay-mixin_-_not-okay-property: green;
300 }""", """
301 - Don't override custom properties created by Polymer's mixin shim. Set \
302 mixins or documented custom properties directly.
303 --not-okay-mixin_-_not-okay-property: green;""")
304
305 def testCssNoQuotesInUrl(self):
306 self.VerifyContentsProducesOutput("""
307 img {
308 background: url('chrome://resources/images/blah.jpg');
309 background: url("../../folder/hello.png");
310 }""", """
311 - Use single quotes (') instead of double quotes (") in strings.
312 background: url("../../folder/hello.png");
313
314 - Don't use quotes in url().
315 background: url('chrome://resources/images/blah.jpg');
316 background: url("../../folder/hello.png");""")
317
318 def testCssOneRulePerLine(self):
319 self.VerifyContentsProducesOutput("""
320 a:not([hidden]):not(.custom-appearance):not([version=1]):first-of-type,
321 a:not([hidden]):not(.custom-appearance):not([version=1]):first-of-type ~
322 input[type='checkbox']:not([hidden]),
323 div {
324 background: url(chrome://resources/BLAH);
325 rule: value; /* rule: value; */
326 rule: value; rule: value;
327 }
328
329 .remix {
330 --dj: {
331 spin: that;
332 };
333 }
334 """, """
335 - One rule per line (what not to do: color: red; margin: 0;).
336 rule: value; rule: value;""")
337
338 def testCssOneSelectorPerLine(self):
339 self.VerifyContentsProducesOutput("""
340 a,
341 div,a,
342 div,/* Hello! */ span,
343 #id.class([dir=rtl):not(.class):any(a, b, d) {
344 rule: value;
345 }
346
347 a,
348 div,a {
349 some-other: rule here;
350 }""", """
351 - One selector per line (what not to do: a, b {}).
352 div,a,
353 div, span,
354 div,a {""")
355
356 def testCssPseudoElementDoubleColon(self):
357 self.VerifyContentsProducesOutput("""
358 a:href,
359 br::after,
360 ::-webkit-scrollbar-thumb,
361 a:not([empty]):hover:focus:active, /* shouldn't catch here and above */
362 abbr:after,
363 .tree-label:empty:after,
364 b:before,
365 :-WebKit-ScrollBar {
366 rule: value;
367 }""", """
368 - Pseudo-elements should use double colon (i.e. ::after).
369 :after (should be ::after)
370 :after (should be ::after)
371 :before (should be ::before)
372 :-WebKit-ScrollBar (should be ::-WebKit-ScrollBar)
373 """)
374
375 def testCssRgbIfNotGray(self):
376 self.VerifyContentsProducesOutput("""
377 #abc,
378 #aaa,
379 #aabbcc {
380 background: -webkit-linear-gradient(left, from(#abc), to(#def));
381 color: #bad;
382 color: #bada55;
383 }""", """
384 - Use rgb() over #hex when not a shade of gray (like #333).
385 background: -webkit-linear-gradient(left, from(#abc), to(#def)); """
386 """(replace with rgb(170, 187, 204), rgb(221, 238, 255))
387 color: #bad; (replace with rgb(187, 170, 221))
388 color: #bada55; (replace with rgb(186, 218, 85))""")
389
390 def testWebkitBeforeOrAfter(self):
391 self.VerifyContentsProducesOutput("""
392 .test {
393 -webkit-margin-before: 10px;
394 -webkit-margin-start: 20px;
395 -webkit-padding-after: 3px;
396 -webkit-padding-end: 5px;
397 }
398 """, """
399 - Use *-top/bottom instead of -webkit-*-before/after.
400 -webkit-margin-before: 10px; (replace with margin-top)
401 -webkit-padding-after: 3px; (replace with padding-bottom)""")
402
403 def testCssZeroWidthLengths(self):
404 self.VerifyContentsProducesOutput("""
405 @-webkit-keyframe anim {
406 0% { /* Ignore key frames */
407 width: 0px;
408 }
409 10% {
410 width: 10px;
411 }
412 100% {
413 width: 100px;
414 }
415 }
416
417 #logo {
418 background-image: url(images/google_logo.png@2x);
419 }
420
421 body.alternate-logo #logo {
422 -webkit-mask-image: url(images/google_logo.png@2x);
423 }
424
425 /* http://crbug.com/359682 */
426 #spinner-container #spinner {
427 -webkit-animation-duration: 1.0s;
428 }
429
430 .media-button.play > .state0.active,
431 .media-button[state='0'] > .state0.normal /* blah */, /* blee */
432 .media-button[state='0']:not(.disabled):hover > .state0.hover {
433 -webkit-animation: anim 0s;
434 -webkit-animation-duration: anim 0ms;
435 -webkit-transform: scale(0%);
436 background-position-x: 0em;
437 background-position-y: 0ex;
438 border-width: 0em;
439 color: hsl(0, 0%, 85%); /* Shouldn't trigger error. */
440 opacity: .0;
441 opacity: 0.0;
442 opacity: 0.;
443 }
444
445 @page {
446 border-width: 0mm;
447 height: 0cm;
448 width: 0in;
449 }""", """
450 - Use "0" for zero-width lengths (i.e. 0px -> 0)
451 width: 0px;
452 -webkit-transform: scale(0%);
453 background-position-x: 0em;
454 background-position-y: 0ex;
455 border-width: 0em;
456 opacity: .0;
457 opacity: 0.0;
458 opacity: 0.;
459 border-width: 0mm;
460 height: 0cm;
461 width: 0in;
462 """)
463
464 def testInlineStyleInHtml(self):
465 self.VerifyContentsProducesOutput("""<!doctype html>
466 <html>
467 <head>
468 <!-- Don't warn about problems outside of style tags
469 html,
470 body {
471 margin: 0;
472 height: 100%;
473 }
474 -->
475 <style>
476 body {
477 flex-direction:column;
478 }
479 </style>
480 </head>
481 </html>""", """
482 - Colons (:) should have a space after them.
483 flex-direction:column;
484 """, filename='test.html')
485
486 def testInlineStyleInHtmlWithIncludes(self):
487 self.VerifyContentsProducesOutput("""<!doctype html>
488 <html>
489 <style include="fake-shared-css other-shared-css">
490 body {
491 flex-direction:column;
492 }
493 </style>
494 </head>
495 </html>""", """
496 - Colons (:) should have a space after them.
497 flex-direction:column;
498 """, filename='test.html')
499
500 def testInlineSTyleInHtmlWithTagsInComments(self):
501 self.VerifyContentsProducesOutput("""<!doctype html>
502 <html>
503 <style>
504 body {
505 /* You better ignore the <tag> in this comment! */
506 flex-direction:column;
507 }
508 </style>
509 </head>
510 </html>""", """
511 - Colons (:) should have a space after them.
512 flex-direction:column;
513 """, filename='test.html')
514
515
516 if __name__ == '__main__':
517 unittest.main()
OLDNEW
« no previous file with comments | « chrome/browser/web_dev_style/css_checker.py ('k') | chrome/browser/web_dev_style/html_checker.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698