15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Unit tests for Web Development Style Guide checker."""
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import unittest
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)test_dir = os.path.dirname(os.path.abspath(__file__))
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sys.path.extend([
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os.path.normpath(os.path.join(test_dir, '..', '..', '..', 'tools')),
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os.path.join(test_dir),
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)])
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import find_depot_tools # pylint: disable=W0611
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from testing_support.super_mox import SuperMoxTestBase
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from web_dev_style import css_checker, js_checker # pylint: disable=F0401
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class JsStyleGuideTest(SuperMoxTestBase):
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def setUp(self):
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SuperMoxTestBase.setUp(self)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_api = self.mox.CreateMockAnything()
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_api.re = re
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output_api = self.mox.CreateMockAnything()
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.checker = js_checker.JSChecker(input_api, output_api)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetHighlight(self, line, error):
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns the substring of |line| that is highlighted in |error|."""
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_lines = error.split('\n')
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    highlight = error_lines[error_lines.index(line) + 1]
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ''.join(ch1 for (ch1, ch2) in zip(line, highlight) if ch2 == '^')
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ShouldFailConstCheck(self, line):
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks that the 'const' checker flags |line| as a style error."""
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = self.checker.ConstCheck(1, line)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertNotEqual('', error,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Should be flagged as style error: ' + line)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(self.GetHighlight(line, error), 'const')
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ShouldPassConstCheck(self, line):
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks that the 'const' checker doesn't flag |line| as a style error."""
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual('', self.checker.ConstCheck(1, line),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Should not be flagged as style error: ' + line)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testConstFails(self):
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "const foo = 'bar';",
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "    const bar = 'foo';",
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Trying to use |const| as a variable name
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var const = 0;",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var x = 5; const y = 6;",
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "for (var i=0, const e=10; i<e; i++) {",
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "for (const x=0; x<foo; i++) {",
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "while (const x = 7) {",
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.ShouldFailConstCheck(line)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testConstPasses(self):
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # sanity check
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var foo = 'bar'",
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # @const JsDoc tag
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "/** @const */ var SEVEN = 7;",
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # @const tag in multi-line comment
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        " * @const",
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "   * @const",
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # @constructor tag in multi-line comment
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        " * @constructor",
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "   * @constructor",
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # words containing 'const'
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (foo.constructor) {",
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var deconstruction = 'something';",
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var madeUpWordconst = 10;",
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Strings containing the word |const|
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var str = 'const at the beginning';",
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var str = 'At the end: const';",
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # doing this one with regex is probably not practical
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #"var str = 'a const in the middle';",
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.ShouldPassConstCheck(line)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ShouldFailChromeSendCheck(self, line):
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks that the 'chrome.send' checker flags |line| as a style error."""
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = self.checker.ChromeSendCheck(1, line)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertNotEqual('', error,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Should be flagged as style error: ' + line)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(self.GetHighlight(line, error), ', []')
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ShouldPassChromeSendCheck(self, line):
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks that the 'chrome.send' checker doesn't flag |line| as a style
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       error.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual('', self.checker.ChromeSendCheck(1, line),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Should not be flagged as style error: ' + line)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testChromeSendFails(self):
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "chrome.send('message', []);",
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  chrome.send('message', []);",
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.ShouldFailChromeSendCheck(line)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testChromeSendPasses(self):
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "chrome.send('message', constructArgs('foo', []));",
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  chrome.send('message', constructArgs('foo', []));",
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "chrome.send('message', constructArgs([]));",
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  chrome.send('message', constructArgs([]));",
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.ShouldPassChromeSendCheck(line)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ShouldFailGetElementByIdCheck(self, line):
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks that the 'getElementById' checker flags |line| as a style
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       error.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = self.checker.GetElementByIdCheck(1, line)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertNotEqual('', error,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Should be flagged as style error: ' + line)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(self.GetHighlight(line, error), 'document.getElementById')
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ShouldPassGetElementByIdCheck(self, line):
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Checks that the 'getElementById' checker doesn't flag |line| as a style
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       error.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual('', self.checker.GetElementByIdCheck(1, line),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Should not be flagged as style error: ' + line)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testGetElementByIdFails(self):
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "document.getElementById('foo');",
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  document.getElementById('foo');",
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var x = document.getElementById('foo');",
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (document.getElementById('foo').hidden) {",
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.ShouldFailGetElementByIdCheck(line)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testGetElementByIdPasses(self):
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "elem.ownerDocument.getElementById('foo');",
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  elem.ownerDocument.getElementById('foo');",
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var x = elem.ownerDocument.getElementById('foo');",
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (elem.ownerDocument.getElementById('foo').hidden) {",
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "doc.getElementById('foo');",
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  doc.getElementById('foo');",
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "cr.doc.getElementById('foo');",
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  cr.doc.getElementById('foo');",
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "var x = doc.getElementById('foo');",
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (doc.getElementById('foo').hidden) {",
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in lines:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.ShouldPassGetElementByIdCheck(line)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ShouldFailInheritDocCheck(self, line):
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Checks that the '@inheritDoc' checker flags |line| as a style error."""
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error = self.checker.InheritDocCheck(1, line)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertNotEqual('', error,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg='Should be flagged as style error: ' + line)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(self.GetHighlight(line, error), '@inheritDoc')
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ShouldPassInheritDocCheck(self, line):
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Checks that the '@inheritDoc' checker doesn't flag |line| as a style
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       error.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual('', self.checker.InheritDocCheck(1, line),
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg='Should not be flagged as style error: ' + line)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testInheritDocFails(self):
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = [
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " /** @inheritDoc */",
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "   * @inheritDoc",
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ]
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in lines:
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.ShouldFailInheritDocCheck(line)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testInheritDocPasses(self):
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = [
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "And then I said, but I won't @inheritDoc! Hahaha!",
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " If your dad's a doctor, do you inheritDoc?",
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  What's up, inherit doc?",
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "   this.inheritDoc(someDoc)",
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ]
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in lines:
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.ShouldPassInheritDocCheck(line)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ShouldFailWrapperTypeCheck(self, line):
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Checks that the use of wrapper types (i.e. new Number(), @type {Number})
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       is a style error.
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error = self.checker.WrapperTypeCheck(1, line)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertNotEqual('', error,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg='Should be flagged as style error: ' + line)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    highlight = self.GetHighlight(line, error)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(highlight in ('Boolean', 'Number', 'String'))
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ShouldPassWrapperTypeCheck(self, line):
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Checks that the wrapper type checker doesn't flag |line| as a style
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       error.
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual('', self.checker.WrapperTypeCheck(1, line),
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg='Should not be flagged as style error: ' + line)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testWrapperTypePasses(self):
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = [
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "/** @param {!ComplexType} */",
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  * @type {Object}",
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "   * @param {Function=} opt_callback",
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "    * @param {} num Number of things to add to {blah}.",
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "   *  @return {!print_preview.PageNumberSet}",
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " /* @returns {Number} */",  # Should be /** @return {Number} */
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "* @param {!LocalStrings}"
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " Your type of Boolean is false!",
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  Then I parameterized her Number from her friend!",
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "   A String of Pearls",
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "    types.params.aBoolean.typeString(someNumber)",
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ]
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in lines:
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.ShouldPassWrapperTypeCheck(line)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testWrapperTypeFails(self):
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = [
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  /**@type {String}*/(string)",
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "   * @param{Number=} opt_blah A number",
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "/** @private @return {!Boolean} */",
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " * @param {number|String}",
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ]
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in lines:
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.ShouldFailWrapperTypeCheck(line)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ShouldFailVarNameCheck(self, line):
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Checks that var unix_hacker, $dollar are style errors."""
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error = self.checker.VarNameCheck(1, line)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertNotEqual('', error,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg='Should be flagged as style error: ' + line)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    highlight = self.GetHighlight(line, error)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse('var ' in highlight);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def ShouldPassVarNameCheck(self, line):
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Checks that variableNamesLikeThis aren't style errors."""
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual('', self.checker.VarNameCheck(1, line),
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg='Should not be flagged as style error: ' + line)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testVarNameFails(self):
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = [
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "var private_;",
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " var _super_private",
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  var unix_hacker = someFunc();",
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ]
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in lines:
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.ShouldFailVarNameCheck(line)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testVarNamePasses(self):
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = [
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  var namesLikeThis = [];",
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " for (var i = 0; i < 10; ++i) { ",
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "for (var i in obj) {",
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " var one, two, three;",
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  var magnumPI = {};",
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " var g_browser = 'da browzer';",
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "/** @const */ var Bla = options.Bla;",  # goog.scope() replacement.
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " var $ = function() {",                 # For legacy reasons.
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  var StudlyCaps = cr.define('bla')",   # Classes.
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        " var SCARE_SMALL_CHILDREN = [",         # TODO(dbeam): add @const in
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 # front of all these vars like
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "/** @const */ CONST_VAR = 1;",          # this line has (<--).
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ]
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in lines:
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.ShouldPassVarNameCheck(line)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CssStyleGuideTest(SuperMoxTestBase):
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def setUp(self):
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SuperMoxTestBase.setUp(self)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.fake_file_name = 'fake.css'
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.fake_file = self.mox.CreateMockAnything()
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.mox.StubOutWithMock(self.fake_file, 'LocalPath')
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.fake_file.LocalPath().AndReturn(self.fake_file_name)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Actual calls to NewContents() are defined in each test.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.mox.StubOutWithMock(self.fake_file, 'NewContents')
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.input_api = self.mox.CreateMockAnything()
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.input_api.re = re
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.mox.StubOutWithMock(self.input_api, 'AffectedSourceFiles')
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.input_api.AffectedFiles(
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        include_deletes=False, file_filter=None).AndReturn([self.fake_file])
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Actual creations of PresubmitPromptWarning are defined in each test.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.output_api = self.mox.CreateMockAnything()
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.mox.StubOutWithMock(self.output_api, 'PresubmitPromptWarning',
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             use_mock_anything=True)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    author_msg = ('Was the CSS checker useful? '
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  'Send feedback or hate mail to dbeam@chromium.org.')
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.output_api = self.mox.CreateMockAnything()
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.mox.StubOutWithMock(self.output_api, 'PresubmitNotifyResult',
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             use_mock_anything=True)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.output_api.PresubmitNotifyResult(author_msg).AndReturn(None)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def VerifyContentsProducesOutput(self, contents, output):
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.fake_file.NewContents().AndReturn(contents.splitlines())
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.output_api.PresubmitPromptWarning(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.fake_file_name + ':\n' + output.strip()).AndReturn(None)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.mox.ReplayAll()
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    css_checker.CSSChecker(self.input_api, self.output_api).RunChecks()
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssAlphaWithAtBlock(self):
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<include src="../shared/css/cr/ui/overlay.css">
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<include src="chrome://resources/totally-cool.css" />
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A hopefully safely ignored comment and @media statement. /**/
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@media print {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  div {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    display: block;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: red;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).rule {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z-index: 5;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<if expr="not is macosx">
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-image: url(chrome://resources/BLAH); /* TODO(dbeam): Fix this. */
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-color: rgb(235, 239, 249);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</if>
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<if expr="is_macosx">
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-color: white;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-image: url(chrome://resources/BLAH2);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</if>
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: black;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<if expr="is_macosx">
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).language-options-right {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visibility: hidden;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opacity: 1; /* TODO(dbeam): Fix this. */
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</if>""", """
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    display: block;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: red;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    z-index: 5;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: black;""")
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssAlphaWithNonStandard(self):
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* A hopefully safely ignored comment and @media statement. /**/
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: red;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  -webkit-margin-start: 5px;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: red;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    -webkit-margin-start: 5px;""")
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssAlphaWithLongerDashedProps(self):
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  border-left: 5px;  /* A hopefully removed comment. */
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  border: 5px solid red;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border-left: 5px;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border: 5px solid red;""")
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssBracesHaveSpaceBeforeAndNothingAfter(self):
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Hello! */div/* Comment here*/{
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  display: block;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)blah /* hey! */
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule: value;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).this.is { /* allowed */
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule: value;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Start braces ({) end a selector, have a space before them and no rules after.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    div{
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {""")
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssClassesUseDashes(self):
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).className,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).ClassName,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).class-name /* We should not catch this. */,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).class_name {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  display: block;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) - Classes use .dash-form.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    .className,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    .ClassName,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    .class_name {""")
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssCloseBraceOnNewLine(self):
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@media { /* TODO(dbeam) Fix this case. */
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  .rule {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    display: block;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@-webkit-keyframe blah {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  100% { height: -500px 0; }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#rule {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule: value; }""", """
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Always put a rule closing brace (}) on a new line.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rule: value; }""")
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssColonsHaveSpaceAfter(self):
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div:not(.class):not([attr=5]), /* We should not catch this. */
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div:not(.class):not([attr]) /* Nor this. */ {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: url(data:image/jpeg,asdfasdfsadf); /* Ignore this. */
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: -webkit-linear-gradient(left, red,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      80% blah blee blar);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: red;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  display:block;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Colons (:) should have a space after them.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    display:block;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Don't use data URIs in source files. Use grit instead.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background: url(data:image/jpeg,asdfasdfsadf);""")
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssFavorSingleQuotes(self):
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)html[dir="rtl"] body,
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)html[dir=ltr] body /* TODO(dbeam): Require '' around rtl in future? */ {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: url("chrome://resources/BLAH");
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  font-family: "Open Sans";
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<if expr="is_macosx">
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blah: blee;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)</if>
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Use single quotes (') instead of double quotes (") in strings.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html[dir="rtl"] body,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background: url("chrome://resources/BLAH");
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    font-family: "Open Sans";""")
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssHexCouldBeShorter(self):
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#abc,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#abc-,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#abc-ghij,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#abcdef-,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#abcdef-ghij,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#aaaaaa,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#bbaacc {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-color: #336699; /* Ignore short hex rule if not gray. */
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: #999999;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: #666;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Use abbreviated hex (#rgb) when in form #rrggbb.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: #999999; (replace with #999)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Use rgb() over #hex when not a shade of gray (like #333).
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background-color: #336699; (replace with rgb(51, 102, 153))""")
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssUseMillisecondsForSmallTimes(self):
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).transition-0s /* This is gross but may happen. */ {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform: one 0.2s;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform: two .1s;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform: tree 1s;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform: four 300ms;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Use milliseconds for time measurements under 1 second.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transform: one 0.2s; (replace with 200ms)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transform: two .1s; (replace with 100ms)""")
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssNoDataUrisInSourceFiles(self):
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)img {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: url( data:image/jpeg,4\/\/350|\/|3|2 );
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: url('data:image/jpeg,4\/\/350|\/|3|2');
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Don't use data URIs in source files. Use grit instead.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background: url( data:image/jpeg,4\/\/350|\/|3|2 );
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background: url('data:image/jpeg,4\/\/350|\/|3|2');""")
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssOneRulePerLine(self):
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)a:not([hidden]):not(.custom-appearance):not([version=1]):first-of-type,
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)a:not([hidden]):not(.custom-appearance):not([version=1]):first-of-type ~
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input[type='checkbox']:not([hidden]),
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: url(chrome://resources/BLAH);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule: value; /* rule: value; */
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule: value; rule: value;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- One rule per line (what not to do: color: red; margin: 0;).
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rule: value; rule: value;""")
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssOneSelectorPerLine(self):
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)a,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div,a,
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div,/* Hello! */ span,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#id.class([dir=rtl):not(.class):any(a, b, d) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule: value;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)a,
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)div,a {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  some-other: rule here;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- One selector per line (what not to do: a, b {}).
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    div,a,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    div, span,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    div,a {""")
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testCssPseudoElementDoubleColon(self):
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.VerifyContentsProducesOutput("""
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)a:href,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)br::after,
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)::-webkit-scrollbar-thumb,
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)a:not([empty]):hover:focus:active, /* shouldn't catch here and above */
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)abbr:after,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles).tree-label:empty:after,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)b:before,
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles):-WebKit-ScrollBar {
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rule: value;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}""", """
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)- Pseudo-elements should use double colon (i.e. ::after).
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    :after (should be ::after)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    :after (should be ::after)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    :before (should be ::before)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    :-WebKit-ScrollBar (should be ::-WebKit-ScrollBar)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """)
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssRgbIfNotGray(self):
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#abc,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#aaa,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#aabbcc {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background: -webkit-linear-gradient(left, from(#abc), to(#def));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: #bad;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: #bada55;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Use rgb() over #hex when not a shade of gray (like #333).
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background: -webkit-linear-gradient(left, from(#abc), to(#def)); """
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""(replace with rgb(170, 187, 204), rgb(221, 238, 255))
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: #bad; (replace with rgb(187, 170, 221))
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color: #bada55; (replace with rgb(186, 218, 85))""")
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCssZeroLengthTerms(self):
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.VerifyContentsProducesOutput("""
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@-webkit-keyframe anim {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0% { /* Ignore key frames */
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width: 0px;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  10% {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width: 10px;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  100% {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width: 100px;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).media-button.play > .state0.active,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).media-button[state='0'] > .state0.normal /* blah */, /* blee */
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles).media-button[state='0']:not(.disabled):hover > .state0.hover {
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  -webkit-animation: anim 0s;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  -webkit-animation-duration: anim 0ms;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  -webkit-transform: scale(0%),
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     translateX(0deg),
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     translateY(0rad),
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     translateZ(0grad);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-position-x: 0em;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background-position-y: 0ex;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  border-width: 0em;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  color: hsl(0, 0%, 85%); /* Shouldn't trigger error. */
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opacity: .0;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opacity: 0.0;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opacity: 0.;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@page {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  border-width: 0mm;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height: 0cm;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width: 0in;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}""", """
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Make all zero length terms (i.e. 0px) 0 unless inside of hsl() or part of"""
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" @keyframe.
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width: 0px;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    -webkit-animation: anim 0s;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    -webkit-animation-duration: anim 0ms;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    -webkit-transform: scale(0%),
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    translateX(0deg),
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    translateY(0rad),
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    translateZ(0grad);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background-position-x: 0em;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    background-position-y: 0ex;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border-width: 0em;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opacity: .0;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opacity: 0.0;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opacity: 0.;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border-width: 0mm;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height: 0cm;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width: 0in;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""")
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unittest.main()
629