OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library polymer.test.linter_test; | 5 library polymer.test.linter_test; |
6 | 6 |
7 import 'package:polymer/src/build/common.dart'; | 7 import 'package:polymer/src/build/common.dart'; |
8 import 'package:polymer/src/build/linter.dart'; | 8 import 'package:polymer/src/build/linter.dart'; |
9 import 'package:source_maps/span.dart'; | 9 import 'package:source_maps/span.dart'; |
10 import 'package:unittest/compact_vm_config.dart'; | 10 import 'package:unittest/compact_vm_config.dart'; |
11 import 'package:unittest/unittest.dart'; | 11 import 'package:unittest/unittest.dart'; |
12 | 12 |
13 import 'common.dart'; | 13 import 'common.dart'; |
14 | 14 |
15 void main() { | 15 void main() { |
16 useCompactVMConfiguration(); | 16 useCompactVMConfiguration(); |
17 _testLinter('nothing to report', { | 17 _testLinter('nothing to report', { |
18 'a|lib/test.html': '<!DOCTYPE html><html></html>', | 18 'a|lib/test.html': '<!DOCTYPE html><html></html>', |
19 }, { | 19 }, []); |
20 'a|lib/test.html.messages': '' | |
21 }); | |
22 | 20 |
23 group('must have Dart code to invoke initPolymer, dart.js, not boot.js', () { | 21 group('must have Dart code to invoke initPolymer, dart.js, not boot.js', () { |
24 _testLinter('nothing to report', { | 22 _testLinter('nothing to report', { |
25 'a|web/test.html': '<!DOCTYPE html><html>' | 23 'a|web/test.html': '<!DOCTYPE html><html>' |
26 '<script type="application/dart" src="foo.dart">' | 24 '<script type="application/dart" src="foo.dart">' |
27 '</script>' | 25 '</script>' |
28 '<script src="packages/browser/dart.js"></script>' | 26 '<script src="packages/browser/dart.js"></script>' |
29 '</html>', | 27 '</html>', |
30 }, { | 28 }, []); |
31 'a|web/test.html.messages': '', | |
32 }); | |
33 | 29 |
34 _testLinter('missing Dart code and dart.js', { | 30 _testLinter('missing Dart code and dart.js', { |
35 'a|web/test.html': '<!DOCTYPE html><html></html>', | 31 'a|web/test.html': '<!DOCTYPE html><html></html>', |
36 }, { | 32 }, [ |
37 'a|web/test.html.messages': 'error: $USE_INIT_DART', | 33 'error: $USE_INIT_DART', |
38 }); | 34 ]); |
39 | 35 |
40 _testLinter('using deprecated boot.js', { | 36 _testLinter('using deprecated boot.js', { |
41 'a|web/test.html': '<!DOCTYPE html><html>\n' | 37 'a|web/test.html': '<!DOCTYPE html><html>\n' |
42 '<script src="packages/polymer/boot.js"></script>' | 38 '<script src="packages/polymer/boot.js"></script>' |
43 '<script type="application/dart" src="foo.dart">' | 39 '<script type="application/dart" src="foo.dart">' |
44 '</script>' | 40 '</script>' |
45 '<script src="packages/browser/dart.js"></script>' | 41 '<script src="packages/browser/dart.js"></script>' |
46 '</html>', | 42 '</html>', |
47 }, { | 43 }, [ |
48 'a|web/test.html.messages': 'warning: $BOOT_JS_DEPRECATED ' | 44 'warning: $BOOT_JS_DEPRECATED (web/test.html 1 0)', |
49 '(web/test.html 1 0)', | 45 ]); |
50 }); | |
51 }); | 46 }); |
52 group('single script tag per document', () { | 47 group('single script tag per document', () { |
53 _testLinter('two top-level tags', { | 48 _testLinter('two top-level tags', { |
54 'a|web/test.html': '<!DOCTYPE html><html>' | 49 'a|web/test.html': '<!DOCTYPE html><html>' |
55 '<script type="application/dart" src="a.dart">' | 50 '<script type="application/dart" src="a.dart">' |
56 '</script>\n' | 51 '</script>\n' |
57 '<script type="application/dart" src="b.dart">' | 52 '<script type="application/dart" src="b.dart">' |
58 '</script>' | 53 '</script>' |
59 '<script src="packages/browser/dart.js"></script>' | 54 '<script src="packages/browser/dart.js"></script>' |
60 }, { | 55 }, [ |
61 'a|web/test.html.messages': | 56 'warning: Only one "application/dart" script tag per document is' |
62 'warning: Only one "application/dart" script tag per document is' | 57 ' allowed. (web/test.html 1 0)', |
63 ' allowed. (web/test.html 1 0)', | 58 ]); |
64 }); | |
65 | 59 |
66 _testLinter('two top-level tags, non entrypoint', { | 60 _testLinter('two top-level tags, non entrypoint', { |
67 'a|lib/test.html': '<!DOCTYPE html><html>' | 61 'a|lib/test.html': '<!DOCTYPE html><html>' |
68 '<script type="application/dart" src="a.dart">' | 62 '<script type="application/dart" src="a.dart">' |
69 '</script>\n' | 63 '</script>\n' |
70 '<script type="application/dart" src="b.dart">' | 64 '<script type="application/dart" src="b.dart">' |
71 '</script>' | 65 '</script>' |
72 '<script src="packages/browser/dart.js"></script>' | 66 '<script src="packages/browser/dart.js"></script>' |
73 }, { | 67 }, [ |
74 'a|lib/test.html.messages': | 68 'warning: Only one "application/dart" script tag per document is' |
75 'warning: Only one "application/dart" script tag per document is' | 69 ' allowed. (lib/test.html 1 0)', |
76 ' allowed. (lib/test.html 1 0)', | 70 ]); |
77 }); | |
78 | 71 |
79 _testLinter('tags inside elements', { | 72 _testLinter('tags inside elements', { |
80 'a|web/test.html': '<!DOCTYPE html><html>' | 73 'a|web/test.html': '<!DOCTYPE html><html>' |
81 '<polymer-element name="x-a">' | 74 '<polymer-element name="x-a">' |
82 '<script type="application/dart" src="a.dart">' | 75 '<script type="application/dart" src="a.dart">' |
83 '</script>' | 76 '</script>' |
84 '</polymer-element>\n' | 77 '</polymer-element>\n' |
85 '<script type="application/dart" src="b.dart">' | 78 '<script type="application/dart" src="b.dart">' |
86 '</script>' | 79 '</script>' |
87 '<script src="packages/browser/dart.js"></script>' | 80 '<script src="packages/browser/dart.js"></script>' |
88 }, { | 81 }, [ |
89 'a|web/test.html.messages': | 82 'warning: Only one "application/dart" script tag per document is' |
90 'warning: Only one "application/dart" script tag per document is' | 83 ' allowed. (web/test.html 1 0)', |
91 ' allowed. (web/test.html 1 0)', | 84 ]); |
92 }); | |
93 }); | 85 }); |
94 | 86 |
95 group('doctype warning', () { | 87 group('doctype warning', () { |
96 _testLinter('in web', { | 88 _testLinter('in web', { |
97 'a|web/test.html': '<html></html>', | 89 'a|web/test.html': '<html></html>', |
98 }, { | 90 }, [ |
99 'a|web/test.html.messages': | 91 'warning: Unexpected start tag (html). Expected DOCTYPE. ' |
100 'warning: Unexpected start tag (html). Expected DOCTYPE. ' | 92 '(web/test.html 0 0)', |
101 '(web/test.html 0 0)\n' | 93 'error: $USE_INIT_DART', |
102 'error: $USE_INIT_DART', | 94 ]); |
103 }); | |
104 | 95 |
105 _testLinter('in lib', { | 96 _testLinter('in lib', { |
106 'a|lib/test.html': '<html></html>', | 97 'a|lib/test.html': '<html></html>', |
107 }, { | 98 }, []); |
108 'a|lib/test.html.messages': '', | |
109 }); | |
110 }); | 99 }); |
111 | 100 |
112 group('duplicate polymer-elements,', () { | 101 group('duplicate polymer-elements,', () { |
113 _testLinter('same file', { | 102 _testLinter('same file', { |
114 'a|lib/test.html': '''<html> | 103 'a|lib/test.html': '''<html> |
115 <polymer-element name="x-a"></polymer-element> | 104 <polymer-element name="x-a"></polymer-element> |
116 <polymer-element name="x-a"></polymer-element> | 105 <polymer-element name="x-a"></polymer-element> |
117 </html>'''.replaceAll(' ', ''), | 106 </html>'''.replaceAll(' ', ''), |
118 }, { | 107 }, [ |
119 'a|lib/test.html.messages': | 108 'warning: duplicate definition for custom tag "x-a". ' |
120 'warning: duplicate definition for custom tag "x-a". ' | 109 '(lib/test.html 1 0)', |
121 '(lib/test.html 1 0)\n' | 110 'warning: duplicate definition for custom tag "x-a" ' |
122 'warning: duplicate definition for custom tag "x-a" ' | 111 '(second definition). (lib/test.html 2 0)' |
123 '(second definition). (lib/test.html 2 0)' | 112 ]); |
124 }); | |
125 | 113 |
126 _testLinter('other file', { | 114 _testLinter('other file', { |
127 'a|lib/b.html': '''<html> | 115 'a|lib/b.html': '''<html> |
128 <polymer-element name="x-a"></polymer-element> | 116 <polymer-element name="x-a"></polymer-element> |
129 </html>'''.replaceAll(' ', ''), | 117 </html>'''.replaceAll(' ', ''), |
130 'a|lib/test.html': '''<html> | 118 'a|lib/test.html': '''<html> |
131 <link rel="import" href="b.html"> | 119 <link rel="import" href="b.html"> |
132 <polymer-element name="x-a"></polymer-element> | 120 <polymer-element name="x-a"></polymer-element> |
133 </html>'''.replaceAll(' ', ''), | 121 </html>'''.replaceAll(' ', ''), |
134 }, { | 122 }, [ |
135 'a|lib/test.html.messages': | 123 'warning: duplicate definition for custom tag "x-a". ' |
136 'warning: duplicate definition for custom tag "x-a". ' | 124 '(lib/b.html 1 0)', |
137 '(lib/b.html 1 0)\n' | 125 'warning: duplicate definition for custom tag "x-a" ' |
138 'warning: duplicate definition for custom tag "x-a" ' | 126 '(second definition). (lib/test.html 2 0)' |
139 '(second definition). (lib/test.html 2 0)' | 127 ]); |
140 }); | |
141 | 128 |
142 _testLinter('non existing file', { | 129 _testLinter('non existing file', { |
143 'a|lib/test.html': '''<html> | 130 'a|lib/test.html': '''<html> |
144 <link rel="import" href="b.html"> | 131 <link rel="import" href="b.html"> |
145 <polymer-element name="x-a"></polymer-element> | 132 <polymer-element name="x-a"></polymer-element> |
146 </html>'''.replaceAll(' ', ''), | 133 </html>'''.replaceAll(' ', ''), |
147 }, { | 134 }, [ |
148 'a|lib/test.html.messages': | 135 'error: couldn\'t find imported asset "lib/b.html" in package ' |
149 'error: couldn\'t find imported asset "lib/b.html" in package ' | 136 '"a". (lib/test.html 1 0)' |
150 '"a". (lib/test.html 1 0)' | 137 ]); |
151 }); | |
152 | 138 |
153 _testLinter('other package', { | 139 _testLinter('other package', { |
154 'b|lib/b.html': '''<html> | 140 'b|lib/b.html': '''<html> |
155 <polymer-element name="x-a"></polymer-element> | 141 <polymer-element name="x-a"></polymer-element> |
156 </html>'''.replaceAll(' ', ''), | 142 </html>'''.replaceAll(' ', ''), |
157 'a|lib/test.html': '''<html> | 143 'a|lib/test.html': '''<html> |
158 <link rel="import" href="../../packages/b/b.html"> | 144 <link rel="import" href="../../packages/b/b.html"> |
159 <polymer-element name="x-a"></polymer-element> | 145 <polymer-element name="x-a"></polymer-element> |
160 </html>'''.replaceAll(' ', ''), | 146 </html>'''.replaceAll(' ', ''), |
161 }, { | 147 }, [ |
162 'a|lib/test.html.messages': | 148 'warning: duplicate definition for custom tag "x-a". ' |
163 'warning: duplicate definition for custom tag "x-a". ' | 149 '(package:b/b.html 1 0)', |
164 '(package:b/b.html 1 0)\n' | 150 'warning: duplicate definition for custom tag "x-a" ' |
165 'warning: duplicate definition for custom tag "x-a" ' | 151 '(second definition). (lib/test.html 2 0)' |
166 '(second definition). (lib/test.html 2 0)' | 152 ]); |
167 }); | |
168 }); | 153 }); |
169 | 154 |
170 _testLinter('bad link-rel tag (href missing)', { | 155 _testLinter('bad link-rel tag (href missing)', { |
171 'a|lib/test.html': '''<html> | 156 'a|lib/test.html': '''<html> |
172 <link rel="import"> | 157 <link rel="import"> |
173 <link rel="stylesheet"> | 158 <link rel="stylesheet"> |
174 <link rel="foo"> | 159 <link rel="foo"> |
175 <link rel="import" href=""> | 160 <link rel="import" href=""> |
176 </html>'''.replaceAll(' ', ''), | 161 </html>'''.replaceAll(' ', ''), |
177 }, { | 162 }, [ |
178 'a|lib/test.html.messages': | 163 'warning: link rel="import" missing href. (lib/test.html 1 0)', |
179 'warning: link rel="import" missing href. (lib/test.html 1 0)\n' | 164 'warning: link rel="stylesheet" missing href. (lib/test.html 2 0)', |
180 'warning: link rel="stylesheet" missing href. (lib/test.html 2 0)\n' | 165 'warning: link rel="import" missing href. (lib/test.html 4 0)' |
181 'warning: link rel="import" missing href. (lib/test.html 4 0)' | 166 ]); |
182 }); | |
183 | 167 |
184 _testLinter('<element> is not supported', { | 168 _testLinter('<element> is not supported', { |
185 'a|lib/test.html': '''<html> | 169 'a|lib/test.html': '''<html> |
186 <element name="x-a"></element> | 170 <element name="x-a"></element> |
187 </html>'''.replaceAll(' ', ''), | 171 </html>'''.replaceAll(' ', ''), |
188 }, { | 172 }, [ |
189 'a|lib/test.html.messages': | 173 'warning: <element> elements are not supported, use <polymer-element>' |
190 'warning: <element> elements are not supported, use <polymer-element>' | 174 ' instead (lib/test.html 1 0)' |
191 ' instead (lib/test.html 1 0)' | 175 ]); |
192 }); | |
193 | 176 |
194 _testLinter('do not nest <polymer-element>', { | 177 _testLinter('do not nest <polymer-element>', { |
195 'a|lib/test.html': '''<html> | 178 'a|lib/test.html': '''<html> |
196 <polymer-element name="x-a"> | 179 <polymer-element name="x-a"> |
197 <template><div> | 180 <template><div> |
198 <polymer-element name="b"></polymer-element> | 181 <polymer-element name="b"></polymer-element> |
199 </div></template> | 182 </div></template> |
200 </polymer-element> | 183 </polymer-element> |
201 </html>'''.replaceAll(' ', ''), | 184 </html>'''.replaceAll(' ', ''), |
202 }, { | 185 }, [ |
203 'a|lib/test.html.messages': | 186 'error: Nested polymer element definitions are not allowed.' |
204 'error: Nested polymer element definitions are not allowed.' | 187 ' (lib/test.html 3 4)' |
205 ' (lib/test.html 3 4)' | 188 ]); |
206 }); | |
207 | 189 |
208 _testLinter('need a name for <polymer-element>', { | 190 _testLinter('need a name for <polymer-element>', { |
209 'a|lib/test.html': '''<html> | 191 'a|lib/test.html': '''<html> |
210 <polymer-element></polymer-element> | 192 <polymer-element></polymer-element> |
211 </html>'''.replaceAll(' ', ''), | 193 </html>'''.replaceAll(' ', ''), |
212 }, { | 194 }, [ |
213 'a|lib/test.html.messages': | 195 'error: Missing tag name of the custom element. Please include an ' |
214 'error: Missing tag name of the custom element. Please include an ' | 196 'attribute like \'name="your-tag-name"\'. (lib/test.html 1 0)' |
215 'attribute like \'name="your-tag-name"\'. (lib/test.html 1 0)' | 197 ]); |
216 }); | |
217 | 198 |
218 _testLinter('name for <polymer-element> should have dashes', { | 199 _testLinter('name for <polymer-element> should have dashes', { |
219 'a|lib/test.html': '''<html> | 200 'a|lib/test.html': '''<html> |
220 <polymer-element name="a"></polymer-element> | 201 <polymer-element name="a"></polymer-element> |
221 </html>'''.replaceAll(' ', ''), | 202 </html>'''.replaceAll(' ', ''), |
222 }, { | 203 }, [ |
223 'a|lib/test.html.messages': | 204 'error: Invalid name "a". Custom element names must have at least one' |
224 'error: Invalid name "a". Custom element names must have at least one' | 205 ' dash and can\'t be any of the following names: annotation-xml, ' |
225 ' dash and can\'t be any of the following names: annotation-xml, ' | 206 'color-profile, font-face, font-face-src, font-face-uri, ' |
226 'color-profile, font-face, font-face-src, font-face-uri, ' | 207 'font-face-format, font-face-name, missing-glyph. (lib/test.html 1 0)' |
227 'font-face-format, font-face-name, missing-glyph. (lib/test.html 1 0)' | 208 ]); |
228 }); | |
229 | 209 |
230 _testLinter('extend is a valid element or existing tag', { | 210 _testLinter('extend is a valid element or existing tag', { |
231 'a|lib/test.html': '''<html> | 211 'a|lib/test.html': '''<html> |
232 <polymer-element name="x-a" extends="li"></polymer-element> | 212 <polymer-element name="x-a" extends="li"></polymer-element> |
233 </html>'''.replaceAll(' ', ''), | 213 </html>'''.replaceAll(' ', ''), |
234 }, { | 214 }, []); |
235 'a|lib/test.html.messages': '' | |
236 }); | |
237 | 215 |
238 _testLinter('extend is a valid element or existing tag', { | 216 _testLinter('extend is a valid element or existing tag', { |
239 'a|lib/test.html': '''<html> | 217 'a|lib/test.html': '''<html> |
240 <polymer-element name="x-a" extends="x-b"></polymer-element> | 218 <polymer-element name="x-a" extends="x-b"></polymer-element> |
241 </html>'''.replaceAll(' ', ''), | 219 </html>'''.replaceAll(' ', ''), |
242 }, { | 220 }, [ |
243 'a|lib/test.html.messages': '' | 221 'warning: custom element with name "x-b" not found. (lib/test.html 1 0)' |
244 'warning: custom element with name "x-b" not found. ' | 222 ]); |
245 '(lib/test.html 1 0)' | |
246 }); | |
247 | 223 |
248 | 224 |
249 group('script type matches code', () { | 225 group('script type matches code', () { |
250 _testLinter('top-level, .dart url', { | 226 _testLinter('top-level, .dart url', { |
251 'a|lib/test.html': '''<html> | 227 'a|lib/test.html': '''<html> |
252 <script src="foo.dart"></script> | 228 <script src="foo.dart"></script> |
253 </html>'''.replaceAll(' ', ''), | 229 </html>'''.replaceAll(' ', ''), |
254 }, { | 230 }, [ |
255 'a|lib/test.html.messages': | 231 'warning: Wrong script type, expected type="application/dart".' |
256 'warning: Wrong script type, expected type="application/dart".' | 232 ' (lib/test.html 1 0)' |
257 ' (lib/test.html 1 0)' | 233 ]); |
258 }); | |
259 | 234 |
260 _testLinter('in polymer-element, .dart url', { | 235 _testLinter('in polymer-element, .dart url', { |
261 'a|lib/test.html': '''<html> | 236 'a|lib/test.html': '''<html> |
262 <polymer-element name="x-a"> | 237 <polymer-element name="x-a"> |
263 <script src="foo.dart"></script> | 238 <script src="foo.dart"></script> |
264 </polymer-element> | 239 </polymer-element> |
265 </html>'''.replaceAll(' ', ''), | 240 </html>'''.replaceAll(' ', ''), |
266 }, { | 241 }, [ |
267 'a|lib/test.html.messages': | 242 'warning: Wrong script type, expected type="application/dart".' |
268 'warning: Wrong script type, expected type="application/dart".' | 243 ' (lib/test.html 2 0)' |
269 ' (lib/test.html 2 0)' | 244 ]); |
270 }); | |
271 | 245 |
272 _testLinter('in polymer-element, .js url', { | 246 _testLinter('in polymer-element, .js url', { |
273 'a|lib/test.html': '''<html> | 247 'a|lib/test.html': '''<html> |
274 <polymer-element name="x-a"> | 248 <polymer-element name="x-a"> |
275 <script src="foo.js"></script> | 249 <script src="foo.js"></script> |
276 </polymer-element> | 250 </polymer-element> |
277 </html>'''.replaceAll(' ', ''), | 251 </html>'''.replaceAll(' ', ''), |
278 }, { | 252 }, []); |
279 'a|lib/test.html.messages': '' | |
280 }); | |
281 | 253 |
282 _testLinter('in polymer-element, inlined', { | 254 _testLinter('in polymer-element, inlined', { |
283 'a|lib/test.html': '''<html> | 255 'a|lib/test.html': '''<html> |
284 <polymer-element name="x-a"> | 256 <polymer-element name="x-a"> |
285 <script>foo...</script> | 257 <script>foo...</script> |
286 </polymer-element> | 258 </polymer-element> |
287 </html>'''.replaceAll(' ', ''), | 259 </html>'''.replaceAll(' ', ''), |
288 }, { | 260 }, [ |
289 'a|lib/test.html.messages': | 261 'warning: script tag in polymer element with no type will ' |
290 'warning: script tag in polymer element with no type will ' | 262 'be treated as JavaScript. Did you forget type="application/dart"?' |
291 'be treated as JavaScript. Did you forget type="application/dart"?' | 263 ' (lib/test.html 2 0)' |
292 ' (lib/test.html 2 0)' | 264 ]); |
293 }); | |
294 | 265 |
295 _testLinter('top-level, dart type & .dart url', { | 266 _testLinter('top-level, dart type & .dart url', { |
296 'a|lib/test.html': '''<html> | 267 'a|lib/test.html': '''<html> |
297 <script type="application/dart" src="foo.dart"></script> | 268 <script type="application/dart" src="foo.dart"></script> |
298 </html>'''.replaceAll(' ', ''), | 269 </html>'''.replaceAll(' ', ''), |
299 }, { | 270 }, []); |
300 'a|lib/test.html.messages': '' | |
301 }); | |
302 | 271 |
303 _testLinter('top-level, dart type & .js url', { | 272 _testLinter('top-level, dart type & .js url', { |
304 'a|lib/test.html': '''<html> | 273 'a|lib/test.html': '''<html> |
305 <script type="application/dart" src="foo.js"></script> | 274 <script type="application/dart" src="foo.js"></script> |
306 </html>'''.replaceAll(' ', ''), | 275 </html>'''.replaceAll(' ', ''), |
307 }, { | 276 }, [ |
308 'a|lib/test.html.messages': | 277 'warning: "application/dart" scripts should use the .dart file ' |
309 'warning: "application/dart" scripts should use the .dart file ' | 278 'extension. (lib/test.html 1 0)' |
310 'extension. (lib/test.html 1 0)' | 279 ]); |
311 }); | |
312 }); | 280 }); |
313 | 281 |
314 _testLinter('script tags should have only src url or inline code', { | 282 _testLinter('script tags should have only src url or inline code', { |
315 'a|lib/test.html': '''<html> | 283 'a|lib/test.html': '''<html> |
316 <script type="application/dart" src="foo.dart">more</script> | 284 <script type="application/dart" src="foo.dart">more</script> |
317 </html>'''.replaceAll(' ', ''), | 285 </html>'''.replaceAll(' ', ''), |
318 }, { | 286 }, [ |
319 'a|lib/test.html.messages': | 287 'warning: script tag has "src" attribute and also has script text. ' |
320 'warning: script tag has "src" attribute and also has script text. ' | 288 '(lib/test.html 1 0)' |
321 '(lib/test.html 1 0)' | 289 ]); |
322 }); | |
323 | 290 |
324 group('event handlers', () { | 291 group('event handlers', () { |
325 _testLinter('onfoo is not polymer', { | 292 _testLinter('onfoo is not polymer', { |
326 'a|lib/test.html': '''<html><body> | 293 'a|lib/test.html': '''<html><body> |
327 <div onfoo="something"></div> | 294 <div onfoo="something"></div> |
328 '''.replaceAll(' ', ''), | 295 '''.replaceAll(' ', ''), |
329 }, { | 296 }, [ |
330 'a|lib/test.html.messages': | 297 'warning: Event handler "onfoo" will be interpreted as an inline ' |
331 'warning: Event handler "onfoo" will be interpreted as an inline ' | 298 'JavaScript event handler. Use the form ' |
332 'JavaScript event handler. Use the form ' | 299 'on-event-name="handlerName" if you want a Dart handler ' |
333 'on-event-name="handlerName" if you want a Dart handler ' | 300 'that will automatically update the UI based on model changes. ' |
334 'that will automatically update the UI based on model changes. ' | 301 '(lib/test.html 1 5)' |
335 '(lib/test.html 1 5)' | 302 ]); |
336 }); | |
337 | 303 |
338 _testLinter('on-foo is only supported in polymer elements', { | 304 _testLinter('on-foo is only supported in polymer elements', { |
339 'a|lib/test.html': '''<html><body> | 305 'a|lib/test.html': '''<html><body> |
340 <div on-foo="something"></div> | 306 <div on-foo="something"></div> |
341 '''.replaceAll(' ', ''), | 307 '''.replaceAll(' ', ''), |
342 }, { | 308 }, [ |
343 'a|lib/test.html.messages': | 309 'warning: Inline event handlers are only supported inside ' |
344 'warning: Inline event handlers are only supported inside ' | 310 'declarations of <polymer-element>. ' |
345 'declarations of <polymer-element>. ' | 311 '(lib/test.html 1 5)' |
346 '(lib/test.html 1 5)' | 312 ]); |
347 }); | |
348 | 313 |
349 _testLinter('on-foo is not an expression', { | 314 _testLinter('on-foo is not an expression', { |
350 'a|lib/test.html': '''<html><body> | 315 'a|lib/test.html': '''<html><body> |
351 <polymer-element name="x-a"><div on-foo="bar()"></div> | 316 <polymer-element name="x-a"><div on-foo="bar()"></div> |
352 </polymer-element> | 317 </polymer-element> |
353 '''.replaceAll(' ', ''), | 318 '''.replaceAll(' ', ''), |
354 }, { | 319 }, [ |
355 'a|lib/test.html.messages': | 320 'warning: Invalid event handler body "bar()". Declare a method ' |
356 'warning: Invalid event handler body "bar()". Declare a method ' | 321 'in your custom element "void handlerName(event, detail, target)" ' |
357 'in your custom element "void handlerName(event, detail, target)" ' | 322 'and use the form on-foo="handlerName". ' |
358 'and use the form on-foo="handlerName". ' | 323 '(lib/test.html 1 33)' |
359 '(lib/test.html 1 33)' | 324 ]); |
360 }); | |
361 | 325 |
362 _testLinter('on-foo-bar is supported as a custom event name', { | 326 _testLinter('on-foo-bar is supported as a custom event name', { |
363 'a|lib/test.html': '''<html><body> | 327 'a|lib/test.html': '''<html><body> |
364 <polymer-element name="x-a"><div on-foo-bar="quux"></div> | 328 <polymer-element name="x-a"><div on-foo-bar="quux"></div> |
365 </polymer-element> | 329 </polymer-element> |
366 '''.replaceAll(' ', ''), | 330 '''.replaceAll(' ', ''), |
367 }, {}); | 331 }, []); |
368 }); | 332 }); |
369 | 333 |
370 group('using custom tags', () { | 334 group('using custom tags', () { |
371 _testLinter('tag exists (x-tag)', { | 335 _testLinter('tag exists (x-tag)', { |
372 'a|lib/test.html': '<x-foo></x-foo>', | 336 'a|lib/test.html': '<x-foo></x-foo>', |
373 }, { | 337 }, [ |
374 'a|lib/test.html.messages': | 338 'warning: definition for Polymer element with tag name "x-foo" not ' |
375 'warning: definition for Polymer element with tag name "x-foo" not ' | 339 'found. (lib/test.html 0 0)' |
376 'found. (lib/test.html 0 0)' | 340 ]); |
377 }); | |
378 | 341 |
379 _testLinter('tag exists (type extension)', { | 342 _testLinter('tag exists (type extension)', { |
380 'a|lib/test.html': '<div is="x-foo"></div>', | 343 'a|lib/test.html': '<div is="x-foo"></div>', |
381 }, { | 344 }, [ |
382 'a|lib/test.html.messages': | 345 'warning: definition for Polymer element with tag name "x-foo" not ' |
383 'warning: definition for Polymer element with tag name "x-foo" not ' | 346 'found. (lib/test.html 0 0)' |
384 'found. (lib/test.html 0 0)' | 347 ]); |
385 }); | |
386 | 348 |
387 _testLinter('used correctly (no base tag)', { | 349 _testLinter('used correctly (no base tag)', { |
388 'a|lib/test.html': ''' | 350 'a|lib/test.html': ''' |
389 <polymer-element name="x-a"></polymer-element> | 351 <polymer-element name="x-a"></polymer-element> |
390 <x-a></x-a> | 352 <x-a></x-a> |
391 '''.replaceAll(' ', ''), | 353 '''.replaceAll(' ', ''), |
392 }, { | 354 }, []); |
393 'a|lib/test.html.messages': '' | |
394 }); | |
395 | 355 |
396 _testLinter('used incorrectly (no base tag)', { | 356 _testLinter('used incorrectly (no base tag)', { |
397 'a|lib/test.html': ''' | 357 'a|lib/test.html': ''' |
398 <polymer-element name="x-a"></polymer-element> | 358 <polymer-element name="x-a"></polymer-element> |
399 <div is="x-a"></div> | 359 <div is="x-a"></div> |
400 '''.replaceAll(' ', ''), | 360 '''.replaceAll(' ', ''), |
401 }, { | 361 }, [ |
402 'a|lib/test.html.messages': | 362 'warning: custom element "x-a" doesn\'t declare any type ' |
403 'warning: custom element "x-a" doesn\'t declare any type ' | 363 'extensions. To fix this, either rewrite this tag as ' |
404 'extensions. To fix this, either rewrite this tag as ' | 364 '<x-a> or add \'extends="div"\' to ' |
405 '<x-a> or add \'extends="div"\' to ' | 365 'the custom element declaration. (lib/test.html 1 0)' |
406 'the custom element declaration. (lib/test.html 1 0)' | 366 ]); |
407 }); | |
408 | 367 |
409 _testLinter('used incorrectly, imported def (no base tag)', { | 368 _testLinter('used incorrectly, imported def (no base tag)', { |
410 'a|lib/b.html': '<polymer-element name="x-a"></polymer-element>', | 369 'a|lib/b.html': '<polymer-element name="x-a"></polymer-element>', |
411 'a|lib/test.html': ''' | 370 'a|lib/test.html': ''' |
412 <link rel="import" href="b.html"> | 371 <link rel="import" href="b.html"> |
413 <div is="x-a"></div> | 372 <div is="x-a"></div> |
414 '''.replaceAll(' ', ''), | 373 '''.replaceAll(' ', ''), |
415 }, { | 374 }, [ |
416 'a|lib/test.html.messages': | 375 'warning: custom element "x-a" doesn\'t declare any type ' |
417 'warning: custom element "x-a" doesn\'t declare any type ' | 376 'extensions. To fix this, either rewrite this tag as ' |
418 'extensions. To fix this, either rewrite this tag as ' | 377 '<x-a> or add \'extends="div"\' to ' |
419 '<x-a> or add \'extends="div"\' to ' | 378 'the custom element declaration. (lib/test.html 1 0)' |
420 'the custom element declaration. (lib/test.html 1 0)' | 379 ]); |
421 }); | |
422 | 380 |
423 _testLinter('used correctly (base tag)', { | 381 _testLinter('used correctly (base tag)', { |
424 'a|lib/b.html': ''' | 382 'a|lib/b.html': ''' |
425 <polymer-element name="x-a" extends="div"> | 383 <polymer-element name="x-a" extends="div"> |
426 </polymer-element> | 384 </polymer-element> |
427 '''.replaceAll(' ', ''), | 385 '''.replaceAll(' ', ''), |
428 'a|lib/test.html': ''' | 386 'a|lib/test.html': ''' |
429 <link rel="import" href="b.html"> | 387 <link rel="import" href="b.html"> |
430 <div is="x-a"></div> | 388 <div is="x-a"></div> |
431 '''.replaceAll(' ', ''), | 389 '''.replaceAll(' ', ''), |
432 }, { | 390 }, []); |
433 'a|lib/test.html.messages': '' | |
434 }); | |
435 | 391 |
436 _testLinter('used incorrectly (missing base tag)', { | 392 _testLinter('used incorrectly (missing base tag)', { |
437 'a|lib/b.html': ''' | 393 'a|lib/b.html': ''' |
438 <polymer-element name="x-a" extends="div"> | 394 <polymer-element name="x-a" extends="div"> |
439 </polymer-element> | 395 </polymer-element> |
440 '''.replaceAll(' ', ''), | 396 '''.replaceAll(' ', ''), |
441 'a|lib/test.html': ''' | 397 'a|lib/test.html': ''' |
442 <link rel="import" href="b.html"> | 398 <link rel="import" href="b.html"> |
443 <x-a></x-a> | 399 <x-a></x-a> |
444 '''.replaceAll(' ', ''), | 400 '''.replaceAll(' ', ''), |
445 }, { | 401 }, [ |
446 'a|lib/test.html.messages': '' | 402 'warning: custom element "x-a" extends from "div", but this tag ' |
447 'warning: custom element "x-a" extends from "div", but this tag ' | 403 'will not include the default properties of "div". To fix this, ' |
448 'will not include the default properties of "div". To fix this, ' | 404 'either write this tag as <div is="x-a"> or remove the "extends" ' |
449 'either write this tag as <div is="x-a"> or remove the "extends" ' | 405 'attribute from the custom element declaration. (lib/test.html 1 0)' |
450 'attribute from the custom element declaration. (lib/test.html 1 0)' | 406 ]); |
451 }); | |
452 | 407 |
453 _testLinter('used incorrectly (wrong base tag)', { | 408 _testLinter('used incorrectly (wrong base tag)', { |
454 'a|lib/b.html': ''' | 409 'a|lib/b.html': ''' |
455 <polymer-element name="x-a" extends="div"> | 410 <polymer-element name="x-a" extends="div"> |
456 </polymer-element> | 411 </polymer-element> |
457 '''.replaceAll(' ', ''), | 412 '''.replaceAll(' ', ''), |
458 'a|lib/test.html': ''' | 413 'a|lib/test.html': ''' |
459 <link rel="import" href="b.html"> | 414 <link rel="import" href="b.html"> |
460 <span is="x-a"></span> | 415 <span is="x-a"></span> |
461 '''.replaceAll(' ', ''), | 416 '''.replaceAll(' ', ''), |
462 }, { | 417 }, [ |
463 'a|lib/test.html.messages': '' | 418 'warning: custom element "x-a" extends from "div". Did you mean ' |
464 'warning: custom element "x-a" extends from "div". Did you mean ' | 419 'to write <div is="x-a">? (lib/test.html 1 0)' |
465 'to write <div is="x-a">? (lib/test.html 1 0)' | 420 ]); |
466 }); | |
467 | 421 |
468 _testLinter('used incorrectly (wrong base tag, transitive)', { | 422 _testLinter('used incorrectly (wrong base tag, transitive)', { |
469 'a|lib/c.html': ''' | 423 'a|lib/c.html': ''' |
470 <polymer-element name="x-c" extends="li"> | 424 <polymer-element name="x-c" extends="li"> |
471 </polymer-element> | 425 </polymer-element> |
472 <polymer-element name="x-b" extends="x-c"> | 426 <polymer-element name="x-b" extends="x-c"> |
473 </polymer-element> | 427 </polymer-element> |
474 '''.replaceAll(' ', ''), | 428 '''.replaceAll(' ', ''), |
475 'a|lib/b.html': ''' | 429 'a|lib/b.html': ''' |
476 <link rel="import" href="c.html"> | 430 <link rel="import" href="c.html"> |
477 <polymer-element name="x-a" extends="x-b"> | 431 <polymer-element name="x-a" extends="x-b"> |
478 </polymer-element> | 432 </polymer-element> |
479 '''.replaceAll(' ', ''), | 433 '''.replaceAll(' ', ''), |
480 'a|lib/test.html': ''' | 434 'a|lib/test.html': ''' |
481 <link rel="import" href="b.html"> | 435 <link rel="import" href="b.html"> |
482 <span is="x-a"></span> | 436 <span is="x-a"></span> |
483 '''.replaceAll(' ', ''), | 437 '''.replaceAll(' ', ''), |
484 }, { | 438 }, [ |
485 'a|lib/test.html.messages': '' | 439 'warning: custom element "x-a" extends from "li". Did you mean ' |
486 'warning: custom element "x-a" extends from "li". Did you mean ' | 440 'to write <li is="x-a">? (lib/test.html 1 0)' |
487 'to write <li is="x-a">? (lib/test.html 1 0)' | 441 ]); |
488 }); | |
489 }); | 442 }); |
490 | 443 |
491 group('custom attributes', () { | 444 group('custom attributes', () { |
492 _testLinter('foo-bar is no longer supported in attributes', { | 445 _testLinter('foo-bar is no longer supported in attributes', { |
493 'a|lib/test.html': '''<html><body> | 446 'a|lib/test.html': '''<html><body> |
494 <polymer-element name="x-a" attributes="foo-bar"> | 447 <polymer-element name="x-a" attributes="foo-bar"> |
495 </polymer-element> | 448 </polymer-element> |
496 '''.replaceAll(' ', ''), | 449 '''.replaceAll(' ', ''), |
497 }, { | 450 }, [ |
498 'a|lib/test.html.messages': | 451 'warning: PolymerElement no longer recognizes attribute names with ' |
499 'warning: PolymerElement no longer recognizes attribute names with ' | 452 'dashes such as "foo-bar". Use "fooBar" or "foobar" instead (both ' |
500 'dashes such as "foo-bar". Use "fooBar" or "foobar" instead (both ' | 453 'forms are equivalent in HTML). (lib/test.html 1 28)' |
501 'forms are equivalent in HTML). (lib/test.html 1 28)' | 454 ]); |
502 }); | |
503 }); | 455 }); |
504 } | 456 } |
505 | 457 |
506 _testLinter(String name, Map inputFiles, Map outputMessages) { | 458 _testLinter(String name, Map inputFiles, List outputMessages) { |
507 var linter = new Linter(new TransformOptions(), _testFormatter); | 459 var linter = new Linter(new TransformOptions()); |
508 var outputFiles = {}; | 460 var outputFiles = {}; |
509 inputFiles.forEach((k, v) => outputFiles[k] = v); | 461 inputFiles.forEach((k, v) => outputFiles[k] = v); |
510 outputMessages.forEach((k, v) => outputFiles[k] = v); | 462 testPhases(name, [[linter]], inputFiles, outputFiles, outputMessages); |
511 var keys = inputFiles.keys.toSet(); | |
512 keys.retainAll(outputMessages.keys); | |
513 expect(keys, isEmpty); | |
514 testPhases(name, [[linter]], inputFiles, outputFiles); | |
515 } | 463 } |
516 | |
517 | |
518 _testFormatter(String kind, String message, Span span) { | |
519 var formattedMessage = '$kind: $message'; | |
520 if (span != null) { | |
521 formattedMessage = '$formattedMessage ' | |
522 '(${span.sourceUrl} ${span.start.line} ${span.start.column})'; | |
523 } | |
524 return formattedMessage; | |
525 } | |
OLD | NEW |