| Index: chrome/browser/web_dev_style/js_checker_test.py
|
| diff --git a/chrome/browser/web_dev_style/js_checker_test.py b/chrome/browser/web_dev_style/js_checker_test.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..1e28d7968de1583f224666be7bd4a169dc6b4b98
|
| --- /dev/null
|
| +++ b/chrome/browser/web_dev_style/js_checker_test.py
|
| @@ -0,0 +1,329 @@
|
| +#!/usr/bin/env python
|
| +# Copyright 2015 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import js_checker
|
| +from os import path as os_path
|
| +import re
|
| +from sys import path as sys_path
|
| +import test_util
|
| +import unittest
|
| +
|
| +_HERE = os_path.dirname(os_path.abspath(__file__))
|
| +sys_path.append(os_path.join(_HERE, '..', '..', '..', 'tools'))
|
| +
|
| +import find_depot_tools # pylint: disable=W0611
|
| +from testing_support.super_mox import SuperMoxTestBase
|
| +
|
| +
|
| +class JsCheckerTest(SuperMoxTestBase):
|
| + def setUp(self):
|
| + SuperMoxTestBase.setUp(self)
|
| +
|
| + input_api = self.mox.CreateMockAnything()
|
| + input_api.re = re
|
| + output_api = self.mox.CreateMockAnything()
|
| + self.checker = js_checker.JSChecker(input_api, output_api)
|
| +
|
| + def ShouldFailConstCheck(self, line):
|
| + """Checks that the 'const' checker flags |line| as a style error."""
|
| + error = self.checker.ConstCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + 'Should be flagged as style error: ' + line)
|
| + self.assertEqual(test_util.GetHighlight(line, error), 'const')
|
| +
|
| + def ShouldPassConstCheck(self, line):
|
| + """Checks that the 'const' checker doesn't flag |line| as a style error."""
|
| + self.assertEqual('', self.checker.ConstCheck(1, line),
|
| + 'Should not be flagged as style error: ' + line)
|
| +
|
| + def testConstFails(self):
|
| + lines = [
|
| + "const foo = 'bar';",
|
| + " const bar = 'foo';",
|
| +
|
| + # Trying to use |const| as a variable name
|
| + "var const = 0;",
|
| +
|
| + "var x = 5; const y = 6;",
|
| + "for (var i=0, const e=10; i<e; i++) {",
|
| + "for (const x=0; x<foo; i++) {",
|
| + "while (const x = 7) {",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailConstCheck(line)
|
| +
|
| + def testConstPasses(self):
|
| + lines = [
|
| + # sanity check
|
| + "var foo = 'bar'",
|
| +
|
| + # @const JsDoc tag
|
| + "/** @const */ var SEVEN = 7;",
|
| +
|
| + # @const tag in multi-line comment
|
| + " * @const",
|
| + " * @const",
|
| +
|
| + # @constructor tag in multi-line comment
|
| + " * @constructor",
|
| + " * @constructor",
|
| +
|
| + # words containing 'const'
|
| + "if (foo.constructor) {",
|
| + "var deconstruction = 'something';",
|
| + "var madeUpWordconst = 10;",
|
| +
|
| + # Strings containing the word |const|
|
| + "var str = 'const at the beginning';",
|
| + "var str = 'At the end: const';",
|
| +
|
| + # doing this one with regex is probably not practical
|
| + #"var str = 'a const in the middle';",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassConstCheck(line)
|
| +
|
| + def ShouldFailChromeSendCheck(self, line):
|
| + """Checks that the 'chrome.send' checker flags |line| as a style error."""
|
| + error = self.checker.ChromeSendCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + 'Should be flagged as style error: ' + line)
|
| + self.assertEqual(test_util.GetHighlight(line, error), ', []')
|
| +
|
| + def ShouldPassChromeSendCheck(self, line):
|
| + """Checks that the 'chrome.send' checker doesn't flag |line| as a style
|
| + error.
|
| + """
|
| + self.assertEqual('', self.checker.ChromeSendCheck(1, line),
|
| + 'Should not be flagged as style error: ' + line)
|
| +
|
| + def testChromeSendFails(self):
|
| + lines = [
|
| + "chrome.send('message', []);",
|
| + " chrome.send('message', []);",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailChromeSendCheck(line)
|
| +
|
| + def testChromeSendPasses(self):
|
| + lines = [
|
| + "chrome.send('message', constructArgs('foo', []));",
|
| + " chrome.send('message', constructArgs('foo', []));",
|
| + "chrome.send('message', constructArgs([]));",
|
| + " chrome.send('message', constructArgs([]));",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassChromeSendCheck(line)
|
| +
|
| + def ShouldFailEndJsDocCommentCheck(self, line):
|
| + """Checks that the **/ checker flags |line| as a style error."""
|
| + error = self.checker.EndJsDocCommentCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + 'Should be flagged as style error: ' + line)
|
| + self.assertEqual(test_util.GetHighlight(line, error), '**/')
|
| +
|
| + def ShouldPassEndJsDocCommentCheck(self, line):
|
| + """Checks that the **/ checker doesn't flag |line| as a style error."""
|
| + self.assertEqual('', self.checker.EndJsDocCommentCheck(1, line),
|
| + 'Should not be flagged as style error: ' + line)
|
| +
|
| + def testEndJsDocCommentFails(self):
|
| + lines = [
|
| + "/** @override **/",
|
| + "/** @type {number} @const **/",
|
| + " **/",
|
| + "**/ ",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailEndJsDocCommentCheck(line)
|
| +
|
| + def testEndJsDocCommentPasses(self):
|
| + lines = [
|
| + "/***************/", # visual separators
|
| + " */", # valid JSDoc comment ends
|
| + "*/ ",
|
| + "/**/", # funky multi-line comment enders
|
| + "/** @override */", # legit JSDoc one-liners
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassEndJsDocCommentCheck(line)
|
| +
|
| + def ShouldFailExtraDotInGenericCheck(self, line):
|
| + """Checks that Array.< or Object.< is flagged as a style nit."""
|
| + error = self.checker.ExtraDotInGenericCheck(1, line)
|
| + self.assertNotEqual('', error)
|
| + self.assertTrue(test_util.GetHighlight(line, error).endswith(".<"))
|
| +
|
| + def testExtraDotInGenericFails(self):
|
| + lines = [
|
| + "/** @private {!Array.<!Frobber>} */",
|
| + "var a = /** @type {Object.<number>} */({});",
|
| + "* @return {!Promise.<Change>}"
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailExtraDotInGenericCheck(line)
|
| +
|
| + def ShouldFailGetElementByIdCheck(self, line):
|
| + """Checks that the 'getElementById' checker flags |line| as a style
|
| + error.
|
| + """
|
| + error = self.checker.GetElementByIdCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + 'Should be flagged as style error: ' + line)
|
| + self.assertEqual(test_util.GetHighlight(line, error),
|
| + 'document.getElementById')
|
| +
|
| + def ShouldPassGetElementByIdCheck(self, line):
|
| + """Checks that the 'getElementById' checker doesn't flag |line| as a style
|
| + error.
|
| + """
|
| + self.assertEqual('', self.checker.GetElementByIdCheck(1, line),
|
| + 'Should not be flagged as style error: ' + line)
|
| +
|
| + def testGetElementByIdFails(self):
|
| + lines = [
|
| + "document.getElementById('foo');",
|
| + " document.getElementById('foo');",
|
| + "var x = document.getElementById('foo');",
|
| + "if (document.getElementById('foo').hidden) {",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailGetElementByIdCheck(line)
|
| +
|
| + def testGetElementByIdPasses(self):
|
| + lines = [
|
| + "elem.ownerDocument.getElementById('foo');",
|
| + " elem.ownerDocument.getElementById('foo');",
|
| + "var x = elem.ownerDocument.getElementById('foo');",
|
| + "if (elem.ownerDocument.getElementById('foo').hidden) {",
|
| + "doc.getElementById('foo');",
|
| + " doc.getElementById('foo');",
|
| + "cr.doc.getElementById('foo');",
|
| + " cr.doc.getElementById('foo');",
|
| + "var x = doc.getElementById('foo');",
|
| + "if (doc.getElementById('foo').hidden) {",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassGetElementByIdCheck(line)
|
| +
|
| + def ShouldFailInheritDocCheck(self, line):
|
| + """Checks that the '@inheritDoc' checker flags |line| as a style error."""
|
| + error = self.checker.InheritDocCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + msg='Should be flagged as style error: ' + line)
|
| + self.assertEqual(test_util.GetHighlight(line, error), '@inheritDoc')
|
| +
|
| + def ShouldPassInheritDocCheck(self, line):
|
| + """Checks that the '@inheritDoc' checker doesn't flag |line| as a style
|
| + error.
|
| + """
|
| + self.assertEqual('', self.checker.InheritDocCheck(1, line),
|
| + msg='Should not be flagged as style error: ' + line)
|
| +
|
| + def testInheritDocFails(self):
|
| + lines = [
|
| + " /** @inheritDoc */",
|
| + " * @inheritDoc",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailInheritDocCheck(line)
|
| +
|
| + def testInheritDocPasses(self):
|
| + lines = [
|
| + "And then I said, but I won't @inheritDoc! Hahaha!",
|
| + " If your dad's a doctor, do you inheritDoc?",
|
| + " What's up, inherit doc?",
|
| + " this.inheritDoc(someDoc)",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassInheritDocCheck(line)
|
| +
|
| + def ShouldFailWrapperTypeCheck(self, line):
|
| + """Checks that the use of wrapper types (i.e. new Number(), @type {Number})
|
| + is a style error.
|
| + """
|
| + error = self.checker.WrapperTypeCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + msg='Should be flagged as style error: ' + line)
|
| + highlight = test_util.GetHighlight(line, error)
|
| + self.assertTrue(highlight in ('Boolean', 'Number', 'String'))
|
| +
|
| + def ShouldPassWrapperTypeCheck(self, line):
|
| + """Checks that the wrapper type checker doesn't flag |line| as a style
|
| + error.
|
| + """
|
| + self.assertEqual('', self.checker.WrapperTypeCheck(1, line),
|
| + msg='Should not be flagged as style error: ' + line)
|
| +
|
| + def testWrapperTypePasses(self):
|
| + lines = [
|
| + "/** @param {!ComplexType} */",
|
| + " * @type {Object}",
|
| + " * @param {Function=} opt_callback",
|
| + " * @param {} num Number of things to add to {blah}.",
|
| + " * @return {!print_preview.PageNumberSet}",
|
| + " /* @returns {Number} */", # Should be /** @return {Number} */
|
| + "* @param {!LocalStrings}"
|
| + " Your type of Boolean is false!",
|
| + " Then I parameterized her Number from her friend!",
|
| + " A String of Pearls",
|
| + " types.params.aBoolean.typeString(someNumber)",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassWrapperTypeCheck(line)
|
| +
|
| + def testWrapperTypeFails(self):
|
| + lines = [
|
| + " /**@type {String}*/(string)",
|
| + " * @param{Number=} opt_blah A number",
|
| + "/** @private @return {!Boolean} */",
|
| + " * @param {number|String}",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailWrapperTypeCheck(line)
|
| +
|
| + def ShouldFailVarNameCheck(self, line):
|
| + """Checks that var unix_hacker, $dollar are style errors."""
|
| + error = self.checker.VarNameCheck(1, line)
|
| + self.assertNotEqual('', error,
|
| + msg='Should be flagged as style error: ' + line)
|
| + highlight = test_util.GetHighlight(line, error)
|
| + self.assertFalse('var ' in highlight);
|
| +
|
| + def ShouldPassVarNameCheck(self, line):
|
| + """Checks that variableNamesLikeThis aren't style errors."""
|
| + self.assertEqual('', self.checker.VarNameCheck(1, line),
|
| + msg='Should not be flagged as style error: ' + line)
|
| +
|
| + def testVarNameFails(self):
|
| + lines = [
|
| + "var private_;",
|
| + " var _super_private",
|
| + " var unix_hacker = someFunc();",
|
| + ]
|
| + for line in lines:
|
| + self.ShouldFailVarNameCheck(line)
|
| +
|
| + def testVarNamePasses(self):
|
| + lines = [
|
| + " var namesLikeThis = [];",
|
| + " for (var i = 0; i < 10; ++i) { ",
|
| + "for (var i in obj) {",
|
| + " var one, two, three;",
|
| + " var magnumPI = {};",
|
| + " var g_browser = 'da browzer';",
|
| + "/** @const */ var Bla = options.Bla;", # goog.scope() replacement.
|
| + " var $ = function() {", # For legacy reasons.
|
| + " var StudlyCaps = cr.define('bla')", # Classes.
|
| + " var SCARE_SMALL_CHILDREN = [", # TODO(dbeam): add @const in
|
| + # front of all these vars like
|
| + "/** @const */ CONST_VAR = 1;", # this line has (<--).
|
| + ]
|
| + for line in lines:
|
| + self.ShouldPassVarNameCheck(line)
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + unittest.main()
|
|
|