OLD | NEW |
(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 js_checker |
| 7 from os import path as os_path |
| 8 import re |
| 9 from sys import path as sys_path |
| 10 import test_util |
| 11 import unittest |
| 12 |
| 13 _HERE = os_path.dirname(os_path.abspath(__file__)) |
| 14 sys_path.append(os_path.join(_HERE, '..', '..', '..', 'tools')) |
| 15 |
| 16 import find_depot_tools # pylint: disable=W0611 |
| 17 from testing_support.super_mox import SuperMoxTestBase |
| 18 |
| 19 |
| 20 class JsCheckerTest(SuperMoxTestBase): |
| 21 def setUp(self): |
| 22 SuperMoxTestBase.setUp(self) |
| 23 |
| 24 input_api = self.mox.CreateMockAnything() |
| 25 input_api.re = re |
| 26 output_api = self.mox.CreateMockAnything() |
| 27 self.checker = js_checker.JSChecker(input_api, output_api) |
| 28 |
| 29 def ShouldFailConstCheck(self, line): |
| 30 """Checks that the 'const' checker flags |line| as a style error.""" |
| 31 error = self.checker.ConstCheck(1, line) |
| 32 self.assertNotEqual('', error, |
| 33 'Should be flagged as style error: ' + line) |
| 34 self.assertEqual(test_util.GetHighlight(line, error), 'const') |
| 35 |
| 36 def ShouldPassConstCheck(self, line): |
| 37 """Checks that the 'const' checker doesn't flag |line| as a style error.""" |
| 38 self.assertEqual('', self.checker.ConstCheck(1, line), |
| 39 'Should not be flagged as style error: ' + line) |
| 40 |
| 41 def testConstFails(self): |
| 42 lines = [ |
| 43 "const foo = 'bar';", |
| 44 " const bar = 'foo';", |
| 45 |
| 46 # Trying to use |const| as a variable name |
| 47 "var const = 0;", |
| 48 |
| 49 "var x = 5; const y = 6;", |
| 50 "for (var i=0, const e=10; i<e; i++) {", |
| 51 "for (const x=0; x<foo; i++) {", |
| 52 "while (const x = 7) {", |
| 53 ] |
| 54 for line in lines: |
| 55 self.ShouldFailConstCheck(line) |
| 56 |
| 57 def testConstPasses(self): |
| 58 lines = [ |
| 59 # sanity check |
| 60 "var foo = 'bar'", |
| 61 |
| 62 # @const JsDoc tag |
| 63 "/** @const */ var SEVEN = 7;", |
| 64 |
| 65 # @const tag in multi-line comment |
| 66 " * @const", |
| 67 " * @const", |
| 68 |
| 69 # @constructor tag in multi-line comment |
| 70 " * @constructor", |
| 71 " * @constructor", |
| 72 |
| 73 # words containing 'const' |
| 74 "if (foo.constructor) {", |
| 75 "var deconstruction = 'something';", |
| 76 "var madeUpWordconst = 10;", |
| 77 |
| 78 # Strings containing the word |const| |
| 79 "var str = 'const at the beginning';", |
| 80 "var str = 'At the end: const';", |
| 81 |
| 82 # doing this one with regex is probably not practical |
| 83 #"var str = 'a const in the middle';", |
| 84 ] |
| 85 for line in lines: |
| 86 self.ShouldPassConstCheck(line) |
| 87 |
| 88 def ShouldFailChromeSendCheck(self, line): |
| 89 """Checks that the 'chrome.send' checker flags |line| as a style error.""" |
| 90 error = self.checker.ChromeSendCheck(1, line) |
| 91 self.assertNotEqual('', error, |
| 92 'Should be flagged as style error: ' + line) |
| 93 self.assertEqual(test_util.GetHighlight(line, error), ', []') |
| 94 |
| 95 def ShouldPassChromeSendCheck(self, line): |
| 96 """Checks that the 'chrome.send' checker doesn't flag |line| as a style |
| 97 error. |
| 98 """ |
| 99 self.assertEqual('', self.checker.ChromeSendCheck(1, line), |
| 100 'Should not be flagged as style error: ' + line) |
| 101 |
| 102 def testChromeSendFails(self): |
| 103 lines = [ |
| 104 "chrome.send('message', []);", |
| 105 " chrome.send('message', []);", |
| 106 ] |
| 107 for line in lines: |
| 108 self.ShouldFailChromeSendCheck(line) |
| 109 |
| 110 def testChromeSendPasses(self): |
| 111 lines = [ |
| 112 "chrome.send('message', constructArgs('foo', []));", |
| 113 " chrome.send('message', constructArgs('foo', []));", |
| 114 "chrome.send('message', constructArgs([]));", |
| 115 " chrome.send('message', constructArgs([]));", |
| 116 ] |
| 117 for line in lines: |
| 118 self.ShouldPassChromeSendCheck(line) |
| 119 |
| 120 def ShouldFailEndJsDocCommentCheck(self, line): |
| 121 """Checks that the **/ checker flags |line| as a style error.""" |
| 122 error = self.checker.EndJsDocCommentCheck(1, line) |
| 123 self.assertNotEqual('', error, |
| 124 'Should be flagged as style error: ' + line) |
| 125 self.assertEqual(test_util.GetHighlight(line, error), '**/') |
| 126 |
| 127 def ShouldPassEndJsDocCommentCheck(self, line): |
| 128 """Checks that the **/ checker doesn't flag |line| as a style error.""" |
| 129 self.assertEqual('', self.checker.EndJsDocCommentCheck(1, line), |
| 130 'Should not be flagged as style error: ' + line) |
| 131 |
| 132 def testEndJsDocCommentFails(self): |
| 133 lines = [ |
| 134 "/** @override **/", |
| 135 "/** @type {number} @const **/", |
| 136 " **/", |
| 137 "**/ ", |
| 138 ] |
| 139 for line in lines: |
| 140 self.ShouldFailEndJsDocCommentCheck(line) |
| 141 |
| 142 def testEndJsDocCommentPasses(self): |
| 143 lines = [ |
| 144 "/***************/", # visual separators |
| 145 " */", # valid JSDoc comment ends |
| 146 "*/ ", |
| 147 "/**/", # funky multi-line comment enders |
| 148 "/** @override */", # legit JSDoc one-liners |
| 149 ] |
| 150 for line in lines: |
| 151 self.ShouldPassEndJsDocCommentCheck(line) |
| 152 |
| 153 def ShouldFailExtraDotInGenericCheck(self, line): |
| 154 """Checks that Array.< or Object.< is flagged as a style nit.""" |
| 155 error = self.checker.ExtraDotInGenericCheck(1, line) |
| 156 self.assertNotEqual('', error) |
| 157 self.assertTrue(test_util.GetHighlight(line, error).endswith(".<")) |
| 158 |
| 159 def testExtraDotInGenericFails(self): |
| 160 lines = [ |
| 161 "/** @private {!Array.<!Frobber>} */", |
| 162 "var a = /** @type {Object.<number>} */({});", |
| 163 "* @return {!Promise.<Change>}" |
| 164 ] |
| 165 for line in lines: |
| 166 self.ShouldFailExtraDotInGenericCheck(line) |
| 167 |
| 168 def ShouldFailGetElementByIdCheck(self, line): |
| 169 """Checks that the 'getElementById' checker flags |line| as a style |
| 170 error. |
| 171 """ |
| 172 error = self.checker.GetElementByIdCheck(1, line) |
| 173 self.assertNotEqual('', error, |
| 174 'Should be flagged as style error: ' + line) |
| 175 self.assertEqual(test_util.GetHighlight(line, error), |
| 176 'document.getElementById') |
| 177 |
| 178 def ShouldPassGetElementByIdCheck(self, line): |
| 179 """Checks that the 'getElementById' checker doesn't flag |line| as a style |
| 180 error. |
| 181 """ |
| 182 self.assertEqual('', self.checker.GetElementByIdCheck(1, line), |
| 183 'Should not be flagged as style error: ' + line) |
| 184 |
| 185 def testGetElementByIdFails(self): |
| 186 lines = [ |
| 187 "document.getElementById('foo');", |
| 188 " document.getElementById('foo');", |
| 189 "var x = document.getElementById('foo');", |
| 190 "if (document.getElementById('foo').hidden) {", |
| 191 ] |
| 192 for line in lines: |
| 193 self.ShouldFailGetElementByIdCheck(line) |
| 194 |
| 195 def testGetElementByIdPasses(self): |
| 196 lines = [ |
| 197 "elem.ownerDocument.getElementById('foo');", |
| 198 " elem.ownerDocument.getElementById('foo');", |
| 199 "var x = elem.ownerDocument.getElementById('foo');", |
| 200 "if (elem.ownerDocument.getElementById('foo').hidden) {", |
| 201 "doc.getElementById('foo');", |
| 202 " doc.getElementById('foo');", |
| 203 "cr.doc.getElementById('foo');", |
| 204 " cr.doc.getElementById('foo');", |
| 205 "var x = doc.getElementById('foo');", |
| 206 "if (doc.getElementById('foo').hidden) {", |
| 207 ] |
| 208 for line in lines: |
| 209 self.ShouldPassGetElementByIdCheck(line) |
| 210 |
| 211 def ShouldFailInheritDocCheck(self, line): |
| 212 """Checks that the '@inheritDoc' checker flags |line| as a style error.""" |
| 213 error = self.checker.InheritDocCheck(1, line) |
| 214 self.assertNotEqual('', error, |
| 215 msg='Should be flagged as style error: ' + line) |
| 216 self.assertEqual(test_util.GetHighlight(line, error), '@inheritDoc') |
| 217 |
| 218 def ShouldPassInheritDocCheck(self, line): |
| 219 """Checks that the '@inheritDoc' checker doesn't flag |line| as a style |
| 220 error. |
| 221 """ |
| 222 self.assertEqual('', self.checker.InheritDocCheck(1, line), |
| 223 msg='Should not be flagged as style error: ' + line) |
| 224 |
| 225 def testInheritDocFails(self): |
| 226 lines = [ |
| 227 " /** @inheritDoc */", |
| 228 " * @inheritDoc", |
| 229 ] |
| 230 for line in lines: |
| 231 self.ShouldFailInheritDocCheck(line) |
| 232 |
| 233 def testInheritDocPasses(self): |
| 234 lines = [ |
| 235 "And then I said, but I won't @inheritDoc! Hahaha!", |
| 236 " If your dad's a doctor, do you inheritDoc?", |
| 237 " What's up, inherit doc?", |
| 238 " this.inheritDoc(someDoc)", |
| 239 ] |
| 240 for line in lines: |
| 241 self.ShouldPassInheritDocCheck(line) |
| 242 |
| 243 def ShouldFailWrapperTypeCheck(self, line): |
| 244 """Checks that the use of wrapper types (i.e. new Number(), @type {Number}) |
| 245 is a style error. |
| 246 """ |
| 247 error = self.checker.WrapperTypeCheck(1, line) |
| 248 self.assertNotEqual('', error, |
| 249 msg='Should be flagged as style error: ' + line) |
| 250 highlight = test_util.GetHighlight(line, error) |
| 251 self.assertTrue(highlight in ('Boolean', 'Number', 'String')) |
| 252 |
| 253 def ShouldPassWrapperTypeCheck(self, line): |
| 254 """Checks that the wrapper type checker doesn't flag |line| as a style |
| 255 error. |
| 256 """ |
| 257 self.assertEqual('', self.checker.WrapperTypeCheck(1, line), |
| 258 msg='Should not be flagged as style error: ' + line) |
| 259 |
| 260 def testWrapperTypePasses(self): |
| 261 lines = [ |
| 262 "/** @param {!ComplexType} */", |
| 263 " * @type {Object}", |
| 264 " * @param {Function=} opt_callback", |
| 265 " * @param {} num Number of things to add to {blah}.", |
| 266 " * @return {!print_preview.PageNumberSet}", |
| 267 " /* @returns {Number} */", # Should be /** @return {Number} */ |
| 268 "* @param {!LocalStrings}" |
| 269 " Your type of Boolean is false!", |
| 270 " Then I parameterized her Number from her friend!", |
| 271 " A String of Pearls", |
| 272 " types.params.aBoolean.typeString(someNumber)", |
| 273 ] |
| 274 for line in lines: |
| 275 self.ShouldPassWrapperTypeCheck(line) |
| 276 |
| 277 def testWrapperTypeFails(self): |
| 278 lines = [ |
| 279 " /**@type {String}*/(string)", |
| 280 " * @param{Number=} opt_blah A number", |
| 281 "/** @private @return {!Boolean} */", |
| 282 " * @param {number|String}", |
| 283 ] |
| 284 for line in lines: |
| 285 self.ShouldFailWrapperTypeCheck(line) |
| 286 |
| 287 def ShouldFailVarNameCheck(self, line): |
| 288 """Checks that var unix_hacker, $dollar are style errors.""" |
| 289 error = self.checker.VarNameCheck(1, line) |
| 290 self.assertNotEqual('', error, |
| 291 msg='Should be flagged as style error: ' + line) |
| 292 highlight = test_util.GetHighlight(line, error) |
| 293 self.assertFalse('var ' in highlight); |
| 294 |
| 295 def ShouldPassVarNameCheck(self, line): |
| 296 """Checks that variableNamesLikeThis aren't style errors.""" |
| 297 self.assertEqual('', self.checker.VarNameCheck(1, line), |
| 298 msg='Should not be flagged as style error: ' + line) |
| 299 |
| 300 def testVarNameFails(self): |
| 301 lines = [ |
| 302 "var private_;", |
| 303 " var _super_private", |
| 304 " var unix_hacker = someFunc();", |
| 305 ] |
| 306 for line in lines: |
| 307 self.ShouldFailVarNameCheck(line) |
| 308 |
| 309 def testVarNamePasses(self): |
| 310 lines = [ |
| 311 " var namesLikeThis = [];", |
| 312 " for (var i = 0; i < 10; ++i) { ", |
| 313 "for (var i in obj) {", |
| 314 " var one, two, three;", |
| 315 " var magnumPI = {};", |
| 316 " var g_browser = 'da browzer';", |
| 317 "/** @const */ var Bla = options.Bla;", # goog.scope() replacement. |
| 318 " var $ = function() {", # For legacy reasons. |
| 319 " var StudlyCaps = cr.define('bla')", # Classes. |
| 320 " var SCARE_SMALL_CHILDREN = [", # TODO(dbeam): add @const in |
| 321 # front of all these vars like |
| 322 "/** @const */ CONST_VAR = 1;", # this line has (<--). |
| 323 ] |
| 324 for line in lines: |
| 325 self.ShouldPassVarNameCheck(line) |
| 326 |
| 327 |
| 328 if __name__ == '__main__': |
| 329 unittest.main() |
OLD | NEW |