OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # | |
3 # Copyright 2012 The Closure Linter Authors. All Rights Reserved. | |
4 # Licensed under the Apache License, Version 2.0 (the "License"); | |
5 # you may not use this file except in compliance with the License. | |
6 # You may obtain a copy of the License at | |
7 # | |
8 # http://www.apache.org/licenses/LICENSE-2.0 | |
9 # | |
10 # Unless required by applicable law or agreed to in writing, software | |
11 # distributed under the License is distributed on an "AS-IS" BASIS, | |
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 # See the License for the specific language governing permissions and | |
14 # limitations under the License. | |
15 | |
16 """Unit tests for the aliaspass module.""" | |
17 | |
18 # Allow non-Google copyright | |
19 # pylint: disable=g-bad-file-header | |
20 | |
21 __author__ = ('nnaze@google.com (Nathan Naze)') | |
22 | |
23 import unittest as googletest | |
24 | |
25 from closure_linter import aliaspass | |
26 from closure_linter import errors | |
27 from closure_linter import javascriptstatetracker | |
28 from closure_linter import testutil | |
29 from closure_linter.common import erroraccumulator | |
30 | |
31 | |
32 def _GetTokenByLineAndString(start_token, string, line_number): | |
33 for token in start_token: | |
34 if token.line_number == line_number and token.string == string: | |
35 return token | |
36 | |
37 | |
38 class AliasPassTest(googletest.TestCase): | |
39 | |
40 def testInvalidGoogScopeCall(self): | |
41 start_token = testutil.TokenizeSourceAndRunEcmaPass(_TEST_SCOPE_SCRIPT) | |
42 | |
43 error_accumulator = erroraccumulator.ErrorAccumulator() | |
44 alias_pass = aliaspass.AliasPass( | |
45 error_handler=error_accumulator) | |
46 alias_pass.Process(start_token) | |
47 | |
48 alias_errors = error_accumulator.GetErrors() | |
49 self.assertEquals(1, len(alias_errors)) | |
50 | |
51 alias_error = alias_errors[0] | |
52 | |
53 self.assertEquals(errors.INVALID_USE_OF_GOOG_SCOPE, alias_error.code) | |
54 self.assertEquals('goog.scope', alias_error.token.string) | |
55 | |
56 def testAliasedIdentifiers(self): | |
57 start_token = testutil.TokenizeSourceAndRunEcmaPass(_TEST_ALIAS_SCRIPT) | |
58 alias_pass = aliaspass.AliasPass(set(['goog', 'myproject'])) | |
59 alias_pass.Process(start_token) | |
60 | |
61 alias_token = _GetTokenByLineAndString(start_token, 'Event', 4) | |
62 self.assertTrue(alias_token.metadata.is_alias_definition) | |
63 | |
64 my_class_token = _GetTokenByLineAndString(start_token, 'myClass', 9) | |
65 self.assertIsNone(my_class_token.metadata.aliased_symbol) | |
66 | |
67 component_token = _GetTokenByLineAndString(start_token, 'Component', 17) | |
68 self.assertEquals('goog.ui.Component', | |
69 component_token.metadata.aliased_symbol) | |
70 | |
71 event_token = _GetTokenByLineAndString(start_token, 'Event.Something', 17) | |
72 self.assertEquals('goog.events.Event.Something', | |
73 event_token.metadata.aliased_symbol) | |
74 | |
75 non_closurized_token = _GetTokenByLineAndString( | |
76 start_token, 'NonClosurizedClass', 18) | |
77 self.assertIsNone(non_closurized_token.metadata.aliased_symbol) | |
78 | |
79 long_start_token = _GetTokenByLineAndString(start_token, 'Event', 24) | |
80 self.assertEquals('goog.events.Event.MultilineIdentifier.someMethod', | |
81 long_start_token.metadata.aliased_symbol) | |
82 | |
83 def testAliasedDoctypes(self): | |
84 """Tests that aliases are correctly expanded within type annotations.""" | |
85 start_token = testutil.TokenizeSourceAndRunEcmaPass(_TEST_ALIAS_SCRIPT) | |
86 tracker = javascriptstatetracker.JavaScriptStateTracker() | |
87 tracker.DocFlagPass(start_token, error_handler=None) | |
88 | |
89 alias_pass = aliaspass.AliasPass(set(['goog', 'myproject'])) | |
90 alias_pass.Process(start_token) | |
91 | |
92 flag_token = _GetTokenByLineAndString(start_token, '@type', 22) | |
93 self.assertEquals( | |
94 'goog.events.Event.<goog.ui.Component,Array<myproject.foo.MyClass>>', | |
95 repr(flag_token.attached_object.jstype)) | |
96 | |
97 def testModuleAlias(self): | |
98 start_token = testutil.TokenizeSourceAndRunEcmaPass(""" | |
99 goog.module('goog.test'); | |
100 var Alias = goog.require('goog.Alias'); | |
101 Alias.use(); | |
102 """) | |
103 alias_pass = aliaspass.AliasPass(set(['goog'])) | |
104 alias_pass.Process(start_token) | |
105 alias_token = _GetTokenByLineAndString(start_token, 'Alias', 3) | |
106 self.assertTrue(alias_token.metadata.is_alias_definition) | |
107 | |
108 def testMultipleGoogScopeCalls(self): | |
109 start_token = testutil.TokenizeSourceAndRunEcmaPass( | |
110 _TEST_MULTIPLE_SCOPE_SCRIPT) | |
111 | |
112 error_accumulator = erroraccumulator.ErrorAccumulator() | |
113 | |
114 alias_pass = aliaspass.AliasPass( | |
115 set(['goog', 'myproject']), | |
116 error_handler=error_accumulator) | |
117 alias_pass.Process(start_token) | |
118 | |
119 alias_errors = error_accumulator.GetErrors() | |
120 | |
121 self.assertEquals(3, len(alias_errors)) | |
122 | |
123 error = alias_errors[0] | |
124 self.assertEquals(errors.INVALID_USE_OF_GOOG_SCOPE, error.code) | |
125 self.assertEquals(7, error.token.line_number) | |
126 | |
127 error = alias_errors[1] | |
128 self.assertEquals(errors.EXTRA_GOOG_SCOPE_USAGE, error.code) | |
129 self.assertEquals(7, error.token.line_number) | |
130 | |
131 error = alias_errors[2] | |
132 self.assertEquals(errors.EXTRA_GOOG_SCOPE_USAGE, error.code) | |
133 self.assertEquals(11, error.token.line_number) | |
134 | |
135 | |
136 _TEST_ALIAS_SCRIPT = """ | |
137 goog.scope(function() { | |
138 var events = goog.events; // scope alias | |
139 var Event = events. | |
140 Event; // nested multiline scope alias | |
141 | |
142 // This should not be registered as an aliased identifier because | |
143 // it appears before the alias. | |
144 var myClass = new MyClass(); | |
145 | |
146 var Component = goog.ui.Component; // scope alias | |
147 var MyClass = myproject.foo.MyClass; // scope alias | |
148 | |
149 // Scope alias of non-Closurized namespace. | |
150 var NonClosurizedClass = aaa.bbb.NonClosurizedClass; | |
151 | |
152 var component = new Component(Event.Something); | |
153 var nonClosurized = NonClosurizedClass(); | |
154 | |
155 /** | |
156 * A created namespace with a really long identifier. | |
157 * @type {events.Event.<Component,Array<MyClass>} | |
158 */ | |
159 Event. | |
160 MultilineIdentifier. | |
161 someMethod = function() {}; | |
162 }); | |
163 """ | |
164 | |
165 _TEST_SCOPE_SCRIPT = """ | |
166 function foo () { | |
167 // This goog.scope call is invalid. | |
168 goog.scope(function() { | |
169 | |
170 }); | |
171 } | |
172 """ | |
173 | |
174 _TEST_MULTIPLE_SCOPE_SCRIPT = """ | |
175 goog.scope(function() { | |
176 // do nothing | |
177 }); | |
178 | |
179 function foo() { | |
180 var test = goog.scope; // We should not see goog.scope mentioned. | |
181 } | |
182 | |
183 // This goog.scope invalid. There can be only one. | |
184 goog.scope(function() { | |
185 | |
186 }); | |
187 """ | |
188 | |
189 | |
190 if __name__ == '__main__': | |
191 googletest.main() | |
OLD | NEW |