1#!/usr/bin/env python
2#
3# Copyright 2012 The Closure Linter Authors. All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS-IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Unit tests for RequireProvideSorter."""
18
19
20
21import unittest as googletest
22from closure_linter import javascripttokens
23from closure_linter import requireprovidesorter
24from closure_linter import testutil
25
26# pylint: disable=g-bad-name
27TokenType = javascripttokens.JavaScriptTokenType
28
29
30class RequireProvideSorterTest(googletest.TestCase):
31  """Tests for RequireProvideSorter."""
32
33  def testGetFixedProvideString(self):
34    """Tests that fixed string constains proper comments also."""
35    input_lines = [
36        'goog.provide(\'package.xyz\');',
37        '/** @suppress {extraprovide} **/',
38        'goog.provide(\'package.abcd\');'
39    ]
40
41    expected_lines = [
42        '/** @suppress {extraprovide} **/',
43        'goog.provide(\'package.abcd\');',
44        'goog.provide(\'package.xyz\');'
45    ]
46
47    token = testutil.TokenizeSourceAndRunEcmaPass(input_lines)
48
49    sorter = requireprovidesorter.RequireProvideSorter()
50    fixed_provide_string = sorter.GetFixedProvideString(token)
51
52    self.assertEquals(expected_lines, fixed_provide_string.splitlines())
53
54  def testGetFixedRequireString(self):
55    """Tests that fixed string constains proper comments also."""
56    input_lines = [
57        'goog.require(\'package.xyz\');',
58        '/** This is needed for scope. **/',
59        'goog.require(\'package.abcd\');'
60    ]
61
62    expected_lines = [
63        '/** This is needed for scope. **/',
64        'goog.require(\'package.abcd\');',
65        'goog.require(\'package.xyz\');'
66    ]
67
68    token = testutil.TokenizeSourceAndRunEcmaPass(input_lines)
69
70    sorter = requireprovidesorter.RequireProvideSorter()
71    fixed_require_string = sorter.GetFixedRequireString(token)
72
73    self.assertEquals(expected_lines, fixed_require_string.splitlines())
74
75  def testFixRequires_removeBlankLines(self):
76    """Tests that blank lines are omitted in sorted goog.require statements."""
77    input_lines = [
78        'goog.provide(\'package.subpackage.Whatever\');',
79        '',
80        'goog.require(\'package.subpackage.ClassB\');',
81        '',
82        'goog.require(\'package.subpackage.ClassA\');'
83    ]
84    expected_lines = [
85        'goog.provide(\'package.subpackage.Whatever\');',
86        '',
87        'goog.require(\'package.subpackage.ClassA\');',
88        'goog.require(\'package.subpackage.ClassB\');'
89    ]
90    token = testutil.TokenizeSourceAndRunEcmaPass(input_lines)
91
92    sorter = requireprovidesorter.RequireProvideSorter()
93    sorter.FixRequires(token)
94
95    self.assertEquals(expected_lines, self._GetLines(token))
96
97  def fixRequiresTest_withTestOnly(self, position):
98    """Regression-tests sorting even with a goog.setTestOnly statement.
99
100    Args:
101      position: The position in the list where to insert the goog.setTestOnly
102                statement. Will be used to test all possible combinations for
103                this test.
104    """
105    input_lines = [
106        'goog.provide(\'package.subpackage.Whatever\');',
107        '',
108        'goog.require(\'package.subpackage.ClassB\');',
109        'goog.require(\'package.subpackage.ClassA\');'
110    ]
111    expected_lines = [
112        'goog.provide(\'package.subpackage.Whatever\');',
113        '',
114        'goog.require(\'package.subpackage.ClassA\');',
115        'goog.require(\'package.subpackage.ClassB\');'
116    ]
117    input_lines.insert(position, 'goog.setTestOnly();')
118    expected_lines.insert(position, 'goog.setTestOnly();')
119
120    token = testutil.TokenizeSourceAndRunEcmaPass(input_lines)
121
122    sorter = requireprovidesorter.RequireProvideSorter()
123    sorter.FixRequires(token)
124
125    self.assertEquals(expected_lines, self._GetLines(token))
126
127  def testFixRequires_withTestOnly(self):
128    """Regression-tests sorting even after a goog.setTestOnly statement."""
129
130    # goog.setTestOnly at first line.
131    self.fixRequiresTest_withTestOnly(position=0)
132
133    # goog.setTestOnly after goog.provide.
134    self.fixRequiresTest_withTestOnly(position=1)
135
136    # goog.setTestOnly before goog.require.
137    self.fixRequiresTest_withTestOnly(position=2)
138
139    # goog.setTestOnly after goog.require.
140    self.fixRequiresTest_withTestOnly(position=4)
141
142  def _GetLines(self, token):
143    """Returns an array of lines based on the specified token stream."""
144    lines = []
145    line = ''
146    while token:
147      line += token.string
148      if token.IsLastInLine():
149        lines.append(line)
150        line = ''
151      token = token.next
152    return lines
153
154if __name__ == '__main__':
155  googletest.main()
156