| OLD | NEW |
| (Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 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 """Unit tests for Web Development Style Guide checker.""" |
| 7 |
| 8 import os |
| 9 import re |
| 10 import sys |
| 11 import unittest |
| 12 |
| 13 test_dir = os.path.dirname(os.path.abspath(__file__)) |
| 14 sys.path.extend([ |
| 15 os.path.normpath(os.path.join(test_dir, '..', '..', '..', 'tools')), |
| 16 os.path.join(test_dir), |
| 17 ]) |
| 18 |
| 19 import find_depot_tools # pylint: disable=W0611 |
| 20 from testing_support.super_mox import SuperMoxTestBase |
| 21 from web_dev_style import css_checker # pylint: disable=F0401 |
| 22 |
| 23 |
| 24 class WebDevStyleGuideTest(SuperMoxTestBase): |
| 25 def setUp(self): |
| 26 SuperMoxTestBase.setUp(self) |
| 27 |
| 28 self.fake_file_name = 'fake.css' |
| 29 |
| 30 self.fake_file = self.mox.CreateMockAnything() |
| 31 self.mox.StubOutWithMock(self.fake_file, 'LocalPath') |
| 32 self.fake_file.LocalPath().AndReturn(self.fake_file_name) |
| 33 # Actual calls to NewContents() are defined in each test. |
| 34 self.mox.StubOutWithMock(self.fake_file, 'NewContents') |
| 35 |
| 36 self.input_api = self.mox.CreateMockAnything() |
| 37 self.input_api.re = re |
| 38 self.mox.StubOutWithMock(self.input_api, 'AffectedSourceFiles') |
| 39 self.input_api.AffectedFiles( |
| 40 include_deletes=False, file_filter=None).AndReturn([self.fake_file]) |
| 41 |
| 42 # Actual creations of PresubmitNotifyResult are defined in each test. |
| 43 self.output_api = self.mox.CreateMockAnything() |
| 44 self.mox.StubOutWithMock(self.output_api, 'PresubmitNotifyResult', |
| 45 use_mock_anything=True) |
| 46 |
| 47 def VerifyContentsProducesOutput(self, contents, output): |
| 48 self.fake_file.NewContents().AndReturn(contents.splitlines()) |
| 49 self.output_api.PresubmitNotifyResult( |
| 50 self.fake_file_name + ':\n' + output.strip()).AndReturn(None) |
| 51 self.mox.ReplayAll() |
| 52 css_checker.CSSChecker(self.input_api, self.output_api).RunChecks() |
| 53 |
| 54 def testCssAlphaWithAtBlock(self): |
| 55 self.VerifyContentsProducesOutput(""" |
| 56 /* A hopefully safely ignored comment and @media statement. /**/ |
| 57 @media print { |
| 58 div { |
| 59 display: block; |
| 60 color: red; |
| 61 } |
| 62 }""", """ |
| 63 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard. |
| 64 display: block; |
| 65 color: red;""") |
| 66 |
| 67 def testCssAlphaWithNonStandard(self): |
| 68 self.VerifyContentsProducesOutput(""" |
| 69 div { |
| 70 /* A hopefully safely ignored comment and @media statement. /**/ |
| 71 color: red; |
| 72 -webkit-margin-start: 5px; |
| 73 }""", """ |
| 74 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard. |
| 75 color: red; |
| 76 -webkit-margin-start: 5px;""") |
| 77 |
| 78 def testCssAlphaWithLongerDashedProps(self): |
| 79 self.VerifyContentsProducesOutput(""" |
| 80 div { |
| 81 border-left: 5px; /* A hopefully removed comment. */ |
| 82 border: 5px solid red; |
| 83 }""", """ |
| 84 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard. |
| 85 border-left: 5px; |
| 86 border: 5px solid red;""") |
| 87 |
| 88 def testCssBracesHaveSpaceBeforeAndNothingAfter(self): |
| 89 self.VerifyContentsProducesOutput(""" |
| 90 /* Hello! */div/* Comment here*/{ |
| 91 display: block; |
| 92 } |
| 93 |
| 94 blah /* hey! */ |
| 95 { |
| 96 rule: value; |
| 97 } |
| 98 |
| 99 .this.is { /* allowed */ |
| 100 rule: value; |
| 101 }""", """ |
| 102 - Start braces ({) end a selector, have a space before them and no rules after. |
| 103 div{ |
| 104 {""") |
| 105 |
| 106 def testCssClassesUseDashes(self): |
| 107 self.VerifyContentsProducesOutput(""" |
| 108 .className, |
| 109 .ClassName, |
| 110 .class-name /* We should not catch this. */, |
| 111 .class_name { |
| 112 display: block; |
| 113 }""", """ |
| 114 - Classes use .dash-form. |
| 115 .className, |
| 116 .ClassName, |
| 117 .class_name {""") |
| 118 |
| 119 def testCssCloseBraceOnNewLine(self): |
| 120 self.VerifyContentsProducesOutput(""" |
| 121 @media { /* TODO(dbeam) Fix this case. |
| 122 .rule { |
| 123 display: block; |
| 124 }} |
| 125 |
| 126 #rule { |
| 127 rule: value; }""", """ |
| 128 - Always put a rule closing brace (}) on a new line. |
| 129 rule: value; }""") |
| 130 |
| 131 def testCssColonsHaveSpaceAfter(self): |
| 132 self.VerifyContentsProducesOutput(""" |
| 133 div:not(.class):not([attr]) /* We should not catch this. */ { |
| 134 display:block; |
| 135 }""", """ |
| 136 - Colons (:) should have a space after them. |
| 137 display:block;""") |
| 138 |
| 139 def testCssFavorSingleQuotes(self): |
| 140 self.VerifyContentsProducesOutput(""" |
| 141 html[dir="rtl"] body, |
| 142 html[dir=ltr] body /* TODO(dbeam): Require '' around rtl in future? */ { |
| 143 background: url("chrome://resources/BLAH"); |
| 144 font-family: "Open Sans"; |
| 145 }""", """ |
| 146 - Use single quotes (') instead of double quotes (") in strings. |
| 147 html[dir="rtl"] body, |
| 148 background: url("chrome://resources/BLAH"); |
| 149 font-family: "Open Sans";""") |
| 150 |
| 151 def testCssHexCouldBeShorter(self): |
| 152 self.VerifyContentsProducesOutput(""" |
| 153 #abc, |
| 154 #abc-, |
| 155 #abc-ghij, |
| 156 #abcdef-, |
| 157 #abcdef-ghij, |
| 158 #aaaaaa, |
| 159 #bbaacc { |
| 160 color: #999999; |
| 161 color: #666; |
| 162 }""", """ |
| 163 - Use abbreviated hex (#rgb) when in form #rrggbb. |
| 164 color: #999999; (replace with #999)""") |
| 165 |
| 166 def testCssUseMillisecondsForSmallTimes(self): |
| 167 self.VerifyContentsProducesOutput(""" |
| 168 .transition-0s /* This is gross but may happen. */ { |
| 169 transform: one 0.2s; |
| 170 transform: two .1s; |
| 171 transform: tree 1s; |
| 172 transform: four 300ms; |
| 173 }""", """ |
| 174 - Use milliseconds for time measurements under 1 second. |
| 175 transform: one 0.2s; (replace with 200ms) |
| 176 transform: two .1s; (replace with 100ms)""") |
| 177 |
| 178 def testCssOneRulePerLine(self): |
| 179 self.VerifyContentsProducesOutput(""" |
| 180 div { |
| 181 rule: value; /* rule: value; */ |
| 182 rule: value; rule: value; |
| 183 }""", """ |
| 184 - One rule per line (what not to do: color: red; margin: 0;). |
| 185 rule: value; rule: value;""") |
| 186 |
| 187 def testCssOneSelectorPerLine(self): |
| 188 self.VerifyContentsProducesOutput(""" |
| 189 a, |
| 190 div,a, |
| 191 div,/* Hello! */ span, |
| 192 #id.class([dir=rtl):not(.class):any(a, b, d) { |
| 193 rule: value; |
| 194 }""", """ |
| 195 - One selector per line (what not to do: a, b {}). |
| 196 div,a, |
| 197 div, span,""") |
| 198 |
| 199 |
| 200 def testCssRgbIfNotGray(self): |
| 201 self.VerifyContentsProducesOutput(""" |
| 202 #abc, |
| 203 #aaa, |
| 204 #aabbcc { |
| 205 background: -webkit-linear-gradient(left, from(#abc), to(#def)); |
| 206 color: #bad; |
| 207 color: #bada55; |
| 208 }""", """ |
| 209 - Use rgb() over #hex when not a shade of gray (like #333). |
| 210 background: -webkit-linear-gradient(left, from(#abc), to(#def)); """ |
| 211 """(replace with rgb(170, 187, 204), rgb(221, 238, 255)) |
| 212 color: #bad; (replace with rgb(187, 170, 221)) |
| 213 color: #bada55; (replace with rgb(186, 218, 85))""") |
| 214 |
| 215 def testCssZeroLengthTerms(self): |
| 216 self.VerifyContentsProducesOutput(""" |
| 217 @-webkit-keyframe anim { |
| 218 0% { /* Ignore key frames */ |
| 219 width: 0px; |
| 220 } |
| 221 10% { |
| 222 width: 10px; |
| 223 } |
| 224 100% { |
| 225 width: 100px; |
| 226 } |
| 227 } |
| 228 .animating { |
| 229 -webkit-animation: anim 0s; |
| 230 -webkit-animation-duration: anim 0ms; |
| 231 -webkit-transform: scale(0%), |
| 232 translateX(0deg), |
| 233 translateY(0rad), |
| 234 translateZ(0grad); |
| 235 background-position-x: 0em; |
| 236 background-position-y: 0ex; |
| 237 border-width: 0em; |
| 238 color: hsl(0, 0%, 85%); /* Shouldn't trigger error. */ |
| 239 } |
| 240 |
| 241 @page { |
| 242 border-width: 0mm; |
| 243 height: 0cm; |
| 244 width: 0in; |
| 245 }""", """ |
| 246 - Make all zero length terms (i.e. 0px) 0 unless inside of hsl() or part of""" |
| 247 """ @keyframe. |
| 248 width: 0px; |
| 249 -webkit-animation: anim 0s; |
| 250 -webkit-animation-duration: anim 0ms; |
| 251 -webkit-transform: scale(0%), |
| 252 translateX(0deg), |
| 253 translateY(0rad), |
| 254 translateZ(0grad); |
| 255 background-position-x: 0em; |
| 256 background-position-y: 0ex; |
| 257 border-width: 0em; |
| 258 border-width: 0mm; |
| 259 height: 0cm; |
| 260 width: 0in; |
| 261 """) |
| 262 |
| 263 if __name__ == '__main__': |
| 264 unittest.main() |
| OLD | NEW |