1#!/usr/bin/env python
2#
3# Copyright 2008 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"""Medium tests for the gpylint auto-fixer."""
18
19__author__ = 'robbyw@google.com (Robby Walker)'
20
21import StringIO
22
23import gflags as flags
24import unittest as googletest
25from closure_linter import checker
26from closure_linter import error_fixer
27
28_RESOURCE_PREFIX = 'closure_linter/testdata'
29
30flags.FLAGS.strict = True
31flags.FLAGS.limited_doc_files = ('dummy.js', 'externs.js')
32flags.FLAGS.closurized_namespaces = ('goog', 'dummy')
33
34
35class FixJsStyleTest(googletest.TestCase):
36  """Test case to for gjslint auto-fixing."""
37
38  def testFixJsStyle(self):
39    test_cases = [['fixjsstyle.in.js', 'fixjsstyle.out.js'],
40                  ['indentation.js', 'fixjsstyle.indentation.out.js']]
41    for [running_input_file, running_output_file] in test_cases:
42      input_filename = None
43      golden_filename = None
44      current_filename = None
45      try:
46        input_filename = '%s/%s' % (_RESOURCE_PREFIX, running_input_file)
47        current_filename = input_filename
48
49        golden_filename = '%s/%s' % (_RESOURCE_PREFIX, running_output_file)
50        current_filename = golden_filename
51      except IOError, ex:
52        raise IOError('Could not find testdata resource for %s: %s' %
53                      (current_filename, ex))
54
55      if running_input_file == 'fixjsstyle.in.js':
56        with open(input_filename) as f:
57          for line in f:
58            # Go to last line.
59            pass
60          self.assertTrue(line == line.rstrip(), '%s file should not end '
61                          'with a new line.' % (input_filename))
62
63      # Autofix the file, sending output to a fake file.
64      actual = StringIO.StringIO()
65      style_checker = checker.JavaScriptStyleChecker(
66          error_fixer.ErrorFixer(actual))
67      style_checker.Check(input_filename)
68
69      # Now compare the files.
70      actual.seek(0)
71      expected = open(golden_filename, 'r')
72
73      self.assertEqual(actual.readlines(), expected.readlines())
74
75  def testMissingExtraAndUnsortedRequires(self):
76    """Tests handling of missing extra and unsorted goog.require statements."""
77    original = [
78        "goog.require('dummy.aa');",
79        "goog.require('dummy.Cc');",
80        "goog.require('dummy.Dd');",
81        "",
82        "var x = new dummy.Bb();",
83        "dummy.Cc.someMethod();",
84        "dummy.aa.someMethod();",
85        ]
86
87    expected = [
88        "goog.require('dummy.Bb');",
89        "goog.require('dummy.Cc');",
90        "goog.require('dummy.aa');",
91        "",
92        "var x = new dummy.Bb();",
93        "dummy.Cc.someMethod();",
94        "dummy.aa.someMethod();",
95        ]
96
97    self._AssertFixes(original, expected)
98
99  def testMissingExtraAndUnsortedProvides(self):
100    """Tests handling of missing extra and unsorted goog.provide statements."""
101    original = [
102        "goog.provide('dummy.aa');",
103        "goog.provide('dummy.Cc');",
104        "goog.provide('dummy.Dd');",
105        "",
106        "dummy.Cc = function() {};",
107        "dummy.Bb = function() {};",
108        "dummy.aa.someMethod = function();",
109        ]
110
111    expected = [
112        "goog.provide('dummy.Bb');",
113        "goog.provide('dummy.Cc');",
114        "goog.provide('dummy.aa');",
115        "",
116        "dummy.Cc = function() {};",
117        "dummy.Bb = function() {};",
118        "dummy.aa.someMethod = function();",
119        ]
120
121    self._AssertFixes(original, expected)
122
123  def testNoRequires(self):
124    """Tests positioning of missing requires without existing requires."""
125    original = [
126        "goog.provide('dummy.Something');",
127        "",
128        "dummy.Something = function() {};",
129        "",
130        "var x = new dummy.Bb();",
131        ]
132
133    expected = [
134        "goog.provide('dummy.Something');",
135        "",
136        "goog.require('dummy.Bb');",
137        "",
138        "dummy.Something = function() {};",
139        "",
140        "var x = new dummy.Bb();",
141        ]
142
143    self._AssertFixes(original, expected)
144
145  def testNoProvides(self):
146    """Tests positioning of missing provides without existing provides."""
147    original = [
148        "goog.require('dummy.Bb');",
149        "",
150        "dummy.Something = function() {};",
151        "",
152        "var x = new dummy.Bb();",
153        ]
154
155    expected = [
156        "goog.provide('dummy.Something');",
157        "",
158        "goog.require('dummy.Bb');",
159        "",
160        "dummy.Something = function() {};",
161        "",
162        "var x = new dummy.Bb();",
163        ]
164
165    self._AssertFixes(original, expected)
166
167  def testGoogScopeIndentation(self):
168    """Tests Handling a typical end-of-scope indentation fix."""
169    original = [
170        'goog.scope(function() {',
171        '  // TODO(brain): Take over the world.',
172        '});  // goog.scope',
173        ]
174
175    expected = [
176        'goog.scope(function() {',
177        '// TODO(brain): Take over the world.',
178        '});  // goog.scope',
179        ]
180
181    self._AssertFixes(original, expected)
182
183  def testMissingEndOfScopeComment(self):
184    """Tests Handling a missing comment at end of goog.scope."""
185    original = [
186        'goog.scope(function() {',
187        '});',
188        ]
189
190    expected = [
191        'goog.scope(function() {',
192        '});  // goog.scope',
193        ]
194
195    self._AssertFixes(original, expected)
196
197  def testMissingEndOfScopeCommentWithOtherComment(self):
198    """Tests handling an irrelevant comment at end of goog.scope."""
199    original = [
200        'goog.scope(function() {',
201        "});  // I don't belong here!",
202        ]
203
204    expected = [
205        'goog.scope(function() {',
206        '});  // goog.scope',
207        ]
208
209    self._AssertFixes(original, expected)
210
211  def testMalformedEndOfScopeComment(self):
212    """Tests Handling a malformed comment at end of goog.scope."""
213    original = [
214        'goog.scope(function() {',
215        '});  // goog.scope FTW',
216        ]
217
218    expected = [
219        'goog.scope(function() {',
220        '});  // goog.scope',
221        ]
222
223    self._AssertFixes(original, expected)
224
225  def _AssertFixes(self, original, expected):
226    """Asserts that the error fixer corrects original to expected."""
227    original = self._GetHeader() + original
228    expected = self._GetHeader() + expected
229
230    actual = StringIO.StringIO()
231    style_checker = checker.JavaScriptStyleChecker(
232        error_fixer.ErrorFixer(actual))
233    style_checker.CheckLines('testing.js', original, False)
234    actual.seek(0)
235
236    expected = [x + '\n' for x in expected]
237
238    self.assertListEqual(actual.readlines(), expected)
239
240  def _GetHeader(self):
241    """Returns a fake header for a JavaScript file."""
242    return [
243        "// Copyright 2011 Google Inc. All Rights Reserved.",
244        "",
245        "/**",
246        " * @fileoverview Fake file overview.",
247        " * @author fake@google.com (Fake Person)",
248        " */",
249        ""
250        ]
251
252
253if __name__ == '__main__':
254  googletest.main()
255