OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library polymer.test.linter_test; | |
6 | |
7 import 'dart:convert'; | |
8 | |
9 import 'package:polymer/src/build/common.dart'; | |
10 import 'package:polymer/src/build/linter.dart'; | |
11 import 'package:polymer/src/build/messages.dart'; | |
12 import 'package:unittest/unittest.dart'; | |
13 | |
14 import 'common.dart'; | |
15 | |
16 void main() { | |
17 _testLinter('nothing to report', { | |
18 'a|lib/test.html': '<!DOCTYPE html><html></html>', | |
19 }, []); | |
20 | |
21 group('must have proper initialization imports', () { | |
22 _testLinter('nothing to report (no polymer use)', { | |
23 'a|web/test.html': '<!DOCTYPE html><html>' | |
24 '<script type="application/dart" src="foo.dart">' | |
25 '</script>' | |
26 '<script src="packages/browser/dart.js"></script>' | |
27 '</html>', | |
28 }, []); | |
29 | |
30 _testLinter('nothing to report (no polymer use with import)', { | |
31 'a|web/test.html': '<!DOCTYPE html><html>' | |
32 '<link rel="import" href="packages/polymer/polymer.html">' | |
33 '<script type="application/dart" src="foo.dart">' | |
34 '</script>' | |
35 '<script src="packages/browser/dart.js"></script>' | |
36 '</html>', | |
37 }, []); | |
38 | |
39 _testLinter('nothing to report (polymer used)', { | |
40 'a|web/test.html': '<!DOCTYPE html><html>' | |
41 '<link rel="import" href="packages/polymer/polymer.html">' | |
42 '<polymer-element name="x-a"></polymer-element>' | |
43 '<script type="application/dart" src="foo.dart">' | |
44 '</script>' | |
45 '<script src="packages/browser/dart.js"></script>' | |
46 '</html>', | |
47 }, []); | |
48 | |
49 _testLinter('nothing to report (polymer imported transitively)', { | |
50 'a|lib/lib.html': '<!DOCTYPE html><html>' | |
51 '<link rel="import" href="../../packages/polymer/polymer.html">', | |
52 'a|web/test.html': '<!DOCTYPE html><html>' | |
53 '<link rel="import" href="packages/a/lib.html">' | |
54 '<polymer-element name="x-a"></polymer-element>' | |
55 '<script type="application/dart" src="foo.dart">' | |
56 '</script>' | |
57 '<script src="packages/browser/dart.js"></script>' | |
58 '</html>', | |
59 }, []); | |
60 | |
61 test('usePolymerHtmlMessage looks right', () { | |
62 _check(int i, String url) { | |
63 expect(_usePolymerHtmlMessage(i), | |
64 contains('<link rel="import" href="$url">')); | |
65 } | |
66 _check(0, 'packages/polymer/polymer.html'); | |
67 _check(1, '../packages/polymer/polymer.html'); | |
68 _check(2, '../../packages/polymer/polymer.html'); | |
69 _check(3, '../../../packages/polymer/polymer.html'); | |
70 }); | |
71 | |
72 _testLinter('missing polymer.html in web', { | |
73 'a|web/test.html': '<!DOCTYPE html><html>\n' | |
74 '<polymer-element name="x-a"></polymer-element>' | |
75 '<script type="application/dart" src="foo.dart">' | |
76 '</script>' | |
77 '<script src="packages/browser/dart.js"></script>' | |
78 '</html>', | |
79 }, [ | |
80 'warning: ${_usePolymerHtmlMessage(0)} ' | |
81 '(web/test.html 1 0)', | |
82 ]); | |
83 | |
84 _testLinter('missing polymer.html in web/foo', { | |
85 'a|web/foo/test.html': '<!DOCTYPE html><html>\n' | |
86 '<polymer-element name="x-a"></polymer-element>' | |
87 '<script type="application/dart" src="foo.dart">' | |
88 '</script>' | |
89 '<script src="packages/browser/dart.js"></script>' | |
90 '</html>', | |
91 }, [ | |
92 'warning: ${_usePolymerHtmlMessage(1)} ' | |
93 '(web/foo/test.html 1 0)', | |
94 ]); | |
95 | |
96 _testLinter('missing polymer.html doesn\'t warn in lib', { | |
97 'a|lib/test.html': '<!DOCTYPE html><html>\n' | |
98 '<polymer-element name="x-a"></polymer-element>' | |
99 '<script type="application/dart" src="foo.dart">' | |
100 '</script>' | |
101 '<script src="packages/browser/dart.js"></script>' | |
102 '</html>', | |
103 }, []); | |
104 | |
105 _testLinter('missing polymer.html doesn\'t warn in lib/foo/bar', { | |
106 'a|lib/foo/bar/test.html': '<!DOCTYPE html><html>\n' | |
107 '<polymer-element name="x-a"></polymer-element>' | |
108 '<script type="application/dart" src="foo.dart">' | |
109 '</script>' | |
110 '<script src="packages/browser/dart.js"></script>' | |
111 '</html>', | |
112 }, []); | |
113 | |
114 _testLinter('missing Dart code', { | |
115 'a|web/test.html': '<!DOCTYPE html><html>' | |
116 '<link rel="import" href="packages/polymer/polymer.html">' | |
117 '<script src="packages/browser/dart.js"></script>' | |
118 '</html>', | |
119 }, ['warning: ${MISSING_INIT_POLYMER.snippet}',]); | |
120 | |
121 _testLinter('nothing to report, experimental with no Dart code', { | |
122 'a|web/test.html': '<!DOCTYPE html><html>' | |
123 '<link rel="import" ' | |
124 'href="packages/polymer/polymer_experimental.html">' | |
125 '<script src="packages/browser/dart.js"></script>' | |
126 '</html>', | |
127 }, []); | |
128 | |
129 _testLinter('experimental cannot have Dart code in main document', { | |
130 'a|web/test.html': '<!DOCTYPE html><html>' | |
131 '<link rel="import" ' | |
132 'href="packages/polymer/polymer_experimental.html">\n' | |
133 '<script type="application/dart" src="foo.dart">' | |
134 '</script>' | |
135 '<script src="packages/browser/dart.js"></script>' | |
136 '</html>', | |
137 }, [ | |
138 'warning: ${NO_DART_SCRIPT_AND_EXPERIMENTAL.snippet} ' | |
139 '(web/test.html 1 0)', | |
140 ]); | |
141 | |
142 _testLinter('missing Dart code and polymer.html', { | |
143 'a|web/test.html': '<!DOCTYPE html><html></html>', | |
144 }, ['warning: ${MISSING_INIT_POLYMER.snippet}',]); | |
145 | |
146 _testLinter('dart_support unnecessary', { | |
147 'a|web/test.html': '<!DOCTYPE html><html>' | |
148 '<script src="packages/web_components/dart_support.js"></script>' | |
149 '<link rel="import" href="../../packages/polymer/polymer.html">' | |
150 '<polymer-element name="x-a"></polymer-element>' | |
151 '<script type="application/dart" src="foo.dart">' | |
152 '</script>' | |
153 '<script src="packages/browser/dart.js"></script>' | |
154 '</html>', | |
155 }, [ | |
156 'warning: ${DART_SUPPORT_NO_LONGER_REQUIRED.snippet} ' | |
157 '(web/test.html 0 21)' | |
158 ]); | |
159 | |
160 _testLinter('webcomponents unnecessary', { | |
161 'a|web/test.html': '<!DOCTYPE html><html>' | |
162 '$WEB_COMPONENTS_JS_TAG' | |
163 '<script type="application/dart" src="foo.dart">' | |
164 '</script>' | |
165 '</html>', | |
166 }, [ | |
167 'warning: ${WEB_COMPONENTS_NO_LONGER_REQUIRED.snippet} ' | |
168 '(web/test.html 0 21)' | |
169 ]); | |
170 | |
171 _testLinter('platform.js -> webcomponents.js', { | |
172 'a|web/test.html': '<!DOCTYPE html><html>' | |
173 '$PLATFORM_JS_TAG' | |
174 '<script type="application/dart" src="foo.dart">' | |
175 '</script>' | |
176 '</html>', | |
177 }, [ | |
178 'warning: ${PLATFORM_JS_RENAMED.snippet} ' | |
179 '(web/test.html 0 21)' | |
180 ]); | |
181 }); | |
182 | |
183 group('single script tag per document', () { | |
184 _testLinter('two top-level tags', { | |
185 'a|web/test.html': '<!DOCTYPE html><html>' | |
186 '<link rel="import" href="packages/polymer/polymer.html">' | |
187 '<script type="application/dart" src="a.dart">' | |
188 '</script>\n' | |
189 '<script type="application/dart" src="b.dart">' | |
190 '</script>' | |
191 '<script src="packages/browser/dart.js"></script>', | |
192 }, ['warning: ${ONLY_ONE_TAG.snippet} (web/test.html 1 0)',]); | |
193 | |
194 _testLinter('two top-level tags, non entrypoint', { | |
195 'a|lib/test.html': '<!DOCTYPE html><html>' | |
196 '<script type="application/dart" src="a.dart">' | |
197 '</script>\n' | |
198 '<script type="application/dart" src="b.dart">' | |
199 '</script>' | |
200 '<script src="packages/browser/dart.js"></script>' | |
201 }, ['warning: ${ONLY_ONE_TAG.snippet} (lib/test.html 1 0)',]); | |
202 | |
203 _testLinter('tags inside elements', { | |
204 'a|web/test.html': '<!DOCTYPE html><html>' | |
205 '<link rel="import" href="packages/polymer/polymer.html">' | |
206 '<polymer-element name="x-a">' | |
207 '<script type="application/dart" src="a.dart">' | |
208 '</script>' | |
209 '</polymer-element>\n' | |
210 '<script type="application/dart" src="b.dart">' | |
211 '</script>' | |
212 '<script src="packages/browser/dart.js"></script>', | |
213 }, ['warning: ${ONLY_ONE_TAG.snippet} (web/test.html 1 0)',]); | |
214 }); | |
215 | |
216 group('doctype warning', () { | |
217 _testLinter('in web', {'a|web/test.html': '<html></html>',}, [ | |
218 'warning: (from html) Unexpected start tag (html). ' | |
219 'Expected DOCTYPE. (web/test.html 0 0)', | |
220 'warning: ${MISSING_INIT_POLYMER.snippet}', | |
221 ]); | |
222 | |
223 _testLinter('in lib', {'a|lib/test.html': '<html></html>',}, []); | |
224 }); | |
225 | |
226 group('duplicate polymer-elements,', () { | |
227 _testLinter('same file', { | |
228 'a|lib/test.html': '''<html> | |
229 <link rel="import" href="../../packages/polymer/polymer.html"> | |
230 <polymer-element name="x-a"></polymer-element> | |
231 <polymer-element name="x-a"></polymer-element> | |
232 </html>'''.replaceAll(' ', ''), | |
233 }, [ | |
234 'warning: ${DUPLICATE_DEFINITION.create( | |
235 {'name': 'x-a', 'second': ''}).snippet} (lib/test.html 2 0)', | |
236 'warning: ${DUPLICATE_DEFINITION.create( | |
237 {'name': 'x-a', 'second': ' (second definition).'}).snippet} ' | |
238 '(lib/test.html 3 0)', | |
239 ]); | |
240 | |
241 _testLinter('other file', { | |
242 'a|lib/b.html': '''<html> | |
243 <link rel="import" href="../../packages/polymer/polymer.html"> | |
244 <polymer-element name="x-a"></polymer-element> | |
245 </html>'''.replaceAll(' ', ''), | |
246 'a|lib/test.html': '''<html> | |
247 <link rel="import" href="b.html"> | |
248 <polymer-element name="x-a"></polymer-element> | |
249 </html>'''.replaceAll(' ', ''), | |
250 }, [ | |
251 'warning: ${DUPLICATE_DEFINITION.create( | |
252 {'name': 'x-a', 'second': ''}).snippet} (lib/b.html 2 0)', | |
253 'warning: ${DUPLICATE_DEFINITION.create( | |
254 {'name': 'x-a', 'second': ' (second definition).'}).snippet} ' | |
255 '(lib/test.html 2 0)', | |
256 ]); | |
257 | |
258 _testLinter('non existing file', { | |
259 'a|lib/test.html': '''<html> | |
260 <link rel="import" href="../../packages/polymer/polymer.html"> | |
261 <link rel="import" href="b.html"> | |
262 <polymer-element name="x-a"></polymer-element> | |
263 </html>'''.replaceAll(' ', ''), | |
264 }, [ | |
265 'warning: ${IMPORT_NOT_FOUND.create( | |
266 {'path': 'lib/b.html', 'package': 'a'}).snippet} ' | |
267 '(lib/test.html 2 0)' | |
268 ]); | |
269 | |
270 _testLinter('other package', { | |
271 'b|lib/b.html': '''<html> | |
272 <link rel="import" href="../../packages/polymer/polymer.html"> | |
273 <polymer-element name="x-a"></polymer-element> | |
274 </html>'''.replaceAll(' ', ''), | |
275 'a|lib/test.html': '''<html> | |
276 <link rel="import" href="../../packages/b/b.html"> | |
277 <polymer-element name="x-a"></polymer-element> | |
278 </html>'''.replaceAll(' ', ''), | |
279 }, [ | |
280 'warning: ${DUPLICATE_DEFINITION.create( | |
281 {'name': 'x-a', 'second': ''}).snippet} (package:b/b.html 2 0)', | |
282 'warning: ${DUPLICATE_DEFINITION.create( | |
283 {'name': 'x-a', 'second': ' (second definition).'}).snippet} ' | |
284 '(lib/test.html 2 0)', | |
285 ]); | |
286 }); | |
287 | |
288 _testLinter('bad link-rel tag (href missing)', { | |
289 'a|lib/test.html': '''<html> | |
290 <link rel="import"> | |
291 <link rel="stylesheet"> | |
292 <link rel="foo"> | |
293 <link rel="import" href=""> | |
294 </html>'''.replaceAll(' ', ''), | |
295 }, [ | |
296 'warning: ${MISSING_HREF.create({'rel': 'import'}).snippet} ' | |
297 '(lib/test.html 1 0)', | |
298 'warning: ${MISSING_HREF.create({'rel': 'stylesheet'}).snippet} ' | |
299 '(lib/test.html 2 0)', | |
300 'warning: ${MISSING_HREF.create({'rel': 'import'}).snippet} ' | |
301 '(lib/test.html 4 0)', | |
302 ]); | |
303 | |
304 _testLinter('<element> is not supported', { | |
305 'a|lib/test.html': '''<html> | |
306 <element name="x-a"></element> | |
307 </html>'''.replaceAll(' ', ''), | |
308 }, ['warning: ${ELEMENT_DEPRECATED_EONS_AGO.snippet} (lib/test.html 1 0)']); | |
309 | |
310 _testLinter('do not nest <polymer-element>', { | |
311 'a|lib/test.html': '''<html> | |
312 <link rel="import" href="../../packages/polymer/polymer.html"> | |
313 <polymer-element name="x-a"> | |
314 <template><div> | |
315 <polymer-element name="b"></polymer-element> | |
316 </div></template> | |
317 </polymer-element> | |
318 </html>'''.replaceAll(' ', ''), | |
319 }, ['error: ${NESTED_POLYMER_ELEMENT.snippet} (lib/test.html 4 4)']); | |
320 | |
321 _testLinter('do put import inside <polymer-element>', { | |
322 'a|lib/b.html': '<html></html>', | |
323 'a|lib/test.html': '''<html> | |
324 <link rel="import" href="../../packages/polymer/polymer.html"> | |
325 <polymer-element name="x-a"> | |
326 <link rel="import" href="b.html"> | |
327 <template><div> | |
328 </div></template> | |
329 </polymer-element> | |
330 </html>'''.replaceAll(' ', ''), | |
331 }, ['error: ${NO_IMPORT_WITHIN_ELEMENT.snippet} (lib/test.html 3 2)']); | |
332 | |
333 _testLinter('need a name for <polymer-element>', { | |
334 'a|lib/test.html': '''<html> | |
335 <link rel="import" href="../../packages/polymer/polymer.html"> | |
336 <polymer-element></polymer-element> | |
337 </html>'''.replaceAll(' ', ''), | |
338 }, ['error: ${MISSING_TAG_NAME.snippet} (lib/test.html 2 0)']); | |
339 | |
340 _testLinter('name for <polymer-element> should have dashes', { | |
341 'a|lib/test.html': '''<html> | |
342 <link rel="import" href="../../packages/polymer/polymer.html"> | |
343 <polymer-element name="a"></polymer-element> | |
344 </html>'''.replaceAll(' ', ''), | |
345 }, [ | |
346 'error: ${INVALID_TAG_NAME.create({'name': 'a'}).snippet} ' | |
347 '(lib/test.html 2 0)' | |
348 ]); | |
349 | |
350 _testLinter('extend is a valid element or existing tag', { | |
351 'a|web/test.html': '''<!DOCTYPE html><html> | |
352 <link rel="import" href="../../packages/polymer/polymer.html"> | |
353 <polymer-element name="x-a" extends="li"></polymer-element> | |
354 <script type="application/dart"> | |
355 export 'package:polymer/init.dart'; | |
356 </script> | |
357 </html>'''.replaceAll(' ', ''), | |
358 }, []); | |
359 | |
360 _testLinter('extend is a valid element or existing tag', { | |
361 'a|web/test.html': '''<!DOCTYPE html><html> | |
362 <link rel="import" href="../../packages/polymer/polymer.html"> | |
363 <polymer-element name="x-a" extends="x-b"></polymer-element> | |
364 <script type="application/dart"> | |
365 export 'package:polymer/init.dart'; | |
366 </script> | |
367 </html>'''.replaceAll(' ', ''), | |
368 }, [ | |
369 'warning: ${CUSTOM_ELEMENT_NOT_FOUND.create({'tag': 'x-b'}).snippet} ' | |
370 '(web/test.html 2 0)' | |
371 ]); | |
372 | |
373 group('script type matches code', () { | |
374 _testLinter('top-level, .dart url', { | |
375 'a|lib/test.html': '''<html> | |
376 <script src="foo.dart"></script> | |
377 </html>'''.replaceAll(' ', ''), | |
378 }, [ | |
379 'warning: Wrong script type, expected type="application/dart".' | |
380 ' (lib/test.html 1 0)' | |
381 ]); | |
382 | |
383 _testLinter('in polymer-element, .dart url', { | |
384 'a|lib/test.html': '''<html> | |
385 <link rel="import" href="../../packages/polymer/polymer.html"> | |
386 <polymer-element name="x-a"> | |
387 <script src="foo.dart"></script> | |
388 </polymer-element> | |
389 </html>'''.replaceAll(' ', ''), | |
390 }, ['warning: ${EXPECTED_DART_MIME_TYPE.snippet} (lib/test.html 3 0)']); | |
391 | |
392 _testLinter('in polymer-element, .js url', { | |
393 'a|lib/test.html': '''<html> | |
394 <link rel="import" href="../../packages/polymer/polymer.html"> | |
395 <polymer-element name="x-a"> | |
396 <script src="foo.js"></script> | |
397 </polymer-element> | |
398 </html>'''.replaceAll(' ', ''), | |
399 }, []); | |
400 | |
401 _testLinter('in polymer-element, inlined', { | |
402 'a|lib/test.html': '''<html> | |
403 <link rel="import" href="../../packages/polymer/polymer.html"> | |
404 <polymer-element name="x-a"> | |
405 <script>foo...</script> | |
406 </polymer-element> | |
407 </html>'''.replaceAll(' ', ''), | |
408 }, []); | |
409 | |
410 _testLinter('top-level, dart type & .dart url', { | |
411 'a|lib/test.html': '''<html> | |
412 <script type="application/dart" src="foo.dart"></script> | |
413 </html>'''.replaceAll(' ', ''), | |
414 }, []); | |
415 | |
416 _testLinter('top-level, dart type & .js url', { | |
417 'a|lib/test.html': '''<html> | |
418 <script type="application/dart" src="foo.js"></script> | |
419 </html>'''.replaceAll(' ', ''), | |
420 }, ['warning: ${EXPECTED_DART_EXTENSION.snippet} (lib/test.html 1 0)']); | |
421 }); | |
422 | |
423 _testLinter('script tags should have at least src url or inline code', { | |
424 'a|lib/test.html': '''<html> | |
425 <script type="application/dart"></script> | |
426 </html>'''.replaceAll(' ', ''), | |
427 }, ['warning: ${SCRIPT_TAG_SEEMS_EMPTY.snippet} (lib/test.html 1 0)']); | |
428 | |
429 _testLinter('script tags should have only src url or inline code', { | |
430 'a|lib/test.html': '''<html> | |
431 <script type="application/dart" src="foo.dart">more</script> | |
432 </html>'''.replaceAll(' ', ''), | |
433 }, [ | |
434 'warning: ${FOUND_BOTH_SCRIPT_SRC_AND_TEXT.snippet} (lib/test.html 1 0)' | |
435 ]); | |
436 | |
437 group('event handlers', () { | |
438 _testLinter('no longer warn about inline onfoo (Javascript)', { | |
439 'a|lib/test.html': '''<html><body> | |
440 <div onfoo="something"></div> | |
441 '''.replaceAll(' ', ''), | |
442 }, []); | |
443 | |
444 _testLinter('no longer warn about on-foo for auto-binding templates', { | |
445 'a|lib/test.html': '''<html><body> | |
446 <template is="auto-binding-dart"> | |
447 <div on-foo="{{something}}"></div> | |
448 <template> | |
449 <div>foo</div> | |
450 </template> | |
451 <div on-foo="{{something}}"></div> | |
452 </template> | |
453 '''.replaceAll(' ', ''), | |
454 }, []); | |
455 | |
456 _testLinter('on-foo is only supported in polymer elements', { | |
457 'a|lib/test.html': '''<html><body> | |
458 <div on-foo="{{something}}"></div> | |
459 '''.replaceAll(' ', ''), | |
460 }, [ | |
461 'warning: ${EVENT_HANDLERS_ONLY_WITHIN_POLYMER.snippet} ' | |
462 '(lib/test.html 1 5)' | |
463 ]); | |
464 | |
465 _testLinter('on-foo uses the {{ binding }} syntax', { | |
466 'a|lib/test.html': '''<html><body> | |
467 <link rel="import" href="../../packages/polymer/polymer.html"> | |
468 <polymer-element name="x-a"><div on-foo="bar"></div> | |
469 </polymer-element> | |
470 '''.replaceAll(' ', ''), | |
471 }, [ | |
472 'warning: ${INVALID_EVENT_HANDLER_BODY.create( | |
473 {'value': 'bar', 'name': 'on-foo'}).snippet} (lib/test.html 2 33)' | |
474 ]); | |
475 | |
476 _testLinter('on-foo is not an expression', { | |
477 'a|lib/test.html': '''<html><body> | |
478 <link rel="import" href="../../packages/polymer/polymer.html"> | |
479 <polymer-element name="x-a"><div on-foo="{{bar()}}"></div> | |
480 </polymer-element> | |
481 '''.replaceAll(' ', ''), | |
482 }, [ | |
483 'warning: ${INVALID_EVENT_HANDLER_BODY.create( | |
484 {'value': '{{bar()}}', 'name': 'on-foo'}).snippet} ' | |
485 '(lib/test.html 2 33)' | |
486 ]); | |
487 | |
488 _testLinter('on-foo can\'t be empty', { | |
489 'a|lib/test.html': '''<html><body> | |
490 <link rel="import" href="../../packages/polymer/polymer.html"> | |
491 <polymer-element name="x-a"><div on-foo="{{}}"></div> | |
492 </polymer-element> | |
493 '''.replaceAll(' ', ''), | |
494 }, [ | |
495 'warning: ${INVALID_EVENT_HANDLER_BODY.create( | |
496 {'value': '{{}}', 'name': 'on-foo'}).snippet} (lib/test.html 2 33)' | |
497 ]); | |
498 | |
499 _testLinter('on-foo can\'t be just space', { | |
500 'a|lib/test.html': '''<html><body> | |
501 <link rel="import" href="../../packages/polymer/polymer.html"> | |
502 <polymer-element name="x-a"><div on-foo="{{ }}"></div> | |
503 </polymer-element> | |
504 '''.replaceAll(' ', ''), | |
505 }, [ | |
506 'warning: ${INVALID_EVENT_HANDLER_BODY.create( | |
507 {'value': '{{ }}', 'name': 'on-foo'}).snippet} (lib/test.html 2 33)' | |
508 ]); | |
509 | |
510 _testLinter('on-foo-bar is supported as a custom event name', { | |
511 'a|lib/test.html': '''<html><body> | |
512 <link rel="import" href="../../packages/polymer/polymer.html"> | |
513 <polymer-element name="x-a"><div on-foo-bar="{{quux}}"></div> | |
514 </polymer-element> | |
515 '''.replaceAll(' ', ''), | |
516 }, []); | |
517 }); | |
518 | |
519 group('using custom tags', () { | |
520 _testLinter('tag exists (x-tag)', { | |
521 'a|web/test.html': '''<!DOCTYPE html> | |
522 <x-foo></x-foo> | |
523 <script type="application/dart"> | |
524 export 'package:polymer/init.dart'; | |
525 </script> | |
526 '''.replaceAll(' ', ''), | |
527 }, [ | |
528 'warning: ${CUSTOM_ELEMENT_NOT_FOUND.create({'tag': 'x-foo'}).snippet} ' | |
529 '(web/test.html 1 0)' | |
530 ]); | |
531 | |
532 _testLinter('tag exists (type extension)', { | |
533 'a|web/test.html': '''<!DOCTYPE html> | |
534 <div is="x-foo"></div> | |
535 <script type="application/dart"> | |
536 export 'package:polymer/init.dart'; | |
537 </script>'''.replaceAll(' ', ''), | |
538 }, [ | |
539 'warning: ${CUSTOM_ELEMENT_NOT_FOUND.create({'tag': 'x-foo'}).snippet} ' | |
540 '(web/test.html 1 0)', | |
541 ]); | |
542 | |
543 _testLinter('tag exists (internally defined in code)', { | |
544 'a|lib/test.html': '<div is="auto-binding-dart"></div>', | |
545 }, []); | |
546 | |
547 _testLinter('used correctly (no base tag)', { | |
548 'a|lib/test.html': ''' | |
549 <link rel="import" href="../../packages/polymer/polymer.html"> | |
550 <polymer-element name="x-a"></polymer-element> | |
551 <x-a></x-a> | |
552 '''.replaceAll(' ', ''), | |
553 }, []); | |
554 | |
555 _testLinter('used incorrectly (no base tag)', { | |
556 'a|lib/test.html': ''' | |
557 <link rel="import" href="../../packages/polymer/polymer.html"> | |
558 <polymer-element name="x-a"></polymer-element> | |
559 <div is="x-a"></div> | |
560 '''.replaceAll(' ', ''), | |
561 }, [ | |
562 'warning: ${BAD_INSTANTIATION_BOGUS_BASE_TAG.create( | |
563 {'tag': 'x-a', 'base': 'div'}).snippet} (lib/test.html 2 0)' | |
564 ]); | |
565 | |
566 _testLinter('used incorrectly, imported def (no base tag)', { | |
567 'a|lib/b.html': ''' | |
568 <link rel="import" href="../../packages/polymer/polymer.html"> | |
569 <polymer-element name="x-a"></polymer-element>''', | |
570 'a|lib/test.html': ''' | |
571 <link rel="import" href="b.html"> | |
572 <div is="x-a"></div> | |
573 '''.replaceAll(' ', ''), | |
574 }, [ | |
575 'warning: ${BAD_INSTANTIATION_BOGUS_BASE_TAG.create( | |
576 {'tag': 'x-a', 'base': 'div'}).snippet} (lib/test.html 1 0)' | |
577 ]); | |
578 | |
579 _testLinter('used correctly (base tag)', { | |
580 'a|lib/b.html': ''' | |
581 <link rel="import" href="../../packages/polymer/polymer.html"> | |
582 <polymer-element name="x-a" extends="div"> | |
583 </polymer-element> | |
584 '''.replaceAll(' ', ''), | |
585 'a|lib/test.html': ''' | |
586 <link rel="import" href="b.html"> | |
587 <div is="x-a"></div> | |
588 '''.replaceAll(' ', ''), | |
589 }, []); | |
590 | |
591 _testLinter('used incorrectly (missing base tag)', { | |
592 'a|lib/b.html': ''' | |
593 <link rel="import" href="../../packages/polymer/polymer.html"> | |
594 <polymer-element name="x-a" extends="div"> | |
595 </polymer-element> | |
596 '''.replaceAll(' ', ''), | |
597 'a|lib/test.html': ''' | |
598 <link rel="import" href="b.html"> | |
599 <x-a></x-a> | |
600 '''.replaceAll(' ', ''), | |
601 }, [ | |
602 'warning: ${BAD_INSTANTIATION_MISSING_BASE_TAG.create( | |
603 {'tag': 'x-a', 'base': 'div'}).snippet} (lib/test.html 1 0)' | |
604 ]); | |
605 | |
606 _testLinter('used incorrectly (wrong base tag)', { | |
607 'a|lib/b.html': ''' | |
608 <link rel="import" href="../../packages/polymer/polymer.html"> | |
609 <polymer-element name="x-a" extends="div"> | |
610 </polymer-element> | |
611 '''.replaceAll(' ', ''), | |
612 'a|lib/test.html': ''' | |
613 <link rel="import" href="b.html"> | |
614 <span is="x-a"></span> | |
615 '''.replaceAll(' ', ''), | |
616 }, [ | |
617 'warning: ${BAD_INSTANTIATION_WRONG_BASE_TAG.create( | |
618 {'tag': 'x-a', 'base': 'div'}).snippet} (lib/test.html 1 0)' | |
619 ]); | |
620 | |
621 _testLinter('used incorrectly (wrong base tag, transitive)', { | |
622 'a|lib/c.html': ''' | |
623 <link rel="import" href="../../packages/polymer/polymer.html"> | |
624 <polymer-element name="x-c" extends="li"> | |
625 </polymer-element> | |
626 <polymer-element name="x-b" extends="x-c"> | |
627 </polymer-element> | |
628 '''.replaceAll(' ', ''), | |
629 'a|lib/b.html': ''' | |
630 <link rel="import" href="../../packages/polymer/polymer.html"> | |
631 <link rel="import" href="c.html"> | |
632 <polymer-element name="x-a" extends="x-b"> | |
633 </polymer-element> | |
634 '''.replaceAll(' ', ''), | |
635 'a|lib/test.html': ''' | |
636 <link rel="import" href="../../packages/polymer/polymer.html"> | |
637 <link rel="import" href="b.html"> | |
638 <span is="x-a"></span> | |
639 '''.replaceAll(' ', ''), | |
640 }, [ | |
641 'warning: ${BAD_INSTANTIATION_WRONG_BASE_TAG.create( | |
642 {'tag': 'x-a', 'base': 'li'}).snippet} (lib/test.html 2 0)' | |
643 ]); | |
644 | |
645 _testLinter('FOUC warning works', { | |
646 'a|web/a.html': ''' | |
647 <!DOCTYPE html> | |
648 <html><body> | |
649 <link rel="import" href="../../packages/polymer/polymer.html"> | |
650 <polymer-element name="my-element" noscript></polymer-element> | |
651 <my-element>hello!</my-element> | |
652 <script type="application/dart"> | |
653 export "package:polymer/init.dart"; | |
654 </script> | |
655 </body></html> | |
656 ''', | |
657 'a|web/b.html': ''' | |
658 <!DOCTYPE html> | |
659 <html><body> | |
660 <link rel="import" href="../../packages/polymer/polymer.html"> | |
661 <polymer-element name="my-element" noscript></polymer-element> | |
662 <div><my-element>hello!</my-element></div> | |
663 <script type="application/dart"> | |
664 export "package:polymer/init.dart"; | |
665 </script> | |
666 </body></html> | |
667 ''', | |
668 'a|web/c.html': ''' | |
669 <!DOCTYPE html> | |
670 <html unresolved><body> | |
671 <link rel="import" href="../../packages/polymer/polymer.html"> | |
672 <polymer-element name="my-element" noscript></polymer-element> | |
673 <my-element>hello!</my-element> | |
674 <script type="application/dart"> | |
675 export "package:polymer/init.dart"; | |
676 </script> | |
677 </body></html> | |
678 ''' | |
679 }, [ | |
680 'warning: ${POSSIBLE_FUOC.snippet} (web/a.html 4 14)', | |
681 'warning: ${POSSIBLE_FUOC.snippet} (web/b.html 4 19)', | |
682 'warning: ${POSSIBLE_FUOC.snippet} (web/c.html 4 14)', | |
683 ]); | |
684 | |
685 _testLinter('FOUC, no false positives.', { | |
686 // Parent has unresolved attribute. | |
687 'a|web/a.html': ''' | |
688 <!DOCTYPE html> | |
689 <html><body> | |
690 <div unresolved> | |
691 <link rel="import" href="../../packages/polymer/polymer.html"> | |
692 <polymer-element name="my-element" noscript></polymer-element> | |
693 <my-element>hello!</my-element> | |
694 </div> | |
695 <script type="application/dart"> | |
696 export "package:polymer/init.dart"; | |
697 </script> | |
698 </body></html> | |
699 ''', | |
700 // Body has unresolved attribute. | |
701 'a|web/b.html': ''' | |
702 <!DOCTYPE html> | |
703 <html><body unresolved> | |
704 <link rel="import" href="../../packages/polymer/polymer.html"> | |
705 <polymer-element name="my-element" noscript></polymer-element> | |
706 <my-element>hello!</my-element> | |
707 <script type="application/dart"> | |
708 export "package:polymer/init.dart"; | |
709 </script> | |
710 </body></html> | |
711 ''', | |
712 // Inside polymer-element tags its fine. | |
713 'a|web/c.html': ''' | |
714 <!DOCTYPE html> | |
715 <html><body> | |
716 <link rel="import" href="../../packages/polymer/polymer.html"> | |
717 <polymer-element name="my-element" noscript></polymer-element> | |
718 <polymer-element name="foo-element"> | |
719 <template><my-element>hello!</my-element></template> | |
720 </polymer-element> | |
721 <script type="application/dart"> | |
722 export "package:polymer/init.dart"; | |
723 </script> | |
724 </body></html> | |
725 ''', | |
726 // Empty custom elements are fine. | |
727 'a|web/d.html': ''' | |
728 <!DOCTYPE html> | |
729 <html><body> | |
730 <link rel="import" href="../../packages/polymer/polymer.html"> | |
731 <polymer-element name="my-element" noscript></polymer-element> | |
732 <my-element></my-element> | |
733 <script type="application/dart"> | |
734 export "package:polymer/init.dart"; | |
735 </script> | |
736 </body></html> | |
737 ''', | |
738 // Entry points only! | |
739 'a|lib/a.html': ''' | |
740 <link rel="import" href="../../packages/polymer/polymer.html"> | |
741 <polymer-element name="my-element" noscript></polymer-element> | |
742 <my-element>hello!</my-element> | |
743 ''', | |
744 }, []); | |
745 }); | |
746 | |
747 group('custom attributes', () { | |
748 _testLinter('foo-bar is no longer supported in attributes', { | |
749 'a|lib/test.html': '''<html><body> | |
750 <link rel="import" href="../../packages/polymer/polymer.html"> | |
751 <polymer-element name="x-a" attributes="foo-bar"> | |
752 </polymer-element> | |
753 '''.replaceAll(' ', ''), | |
754 }, [ | |
755 'warning: ${NO_DASHES_IN_CUSTOM_ATTRIBUTES.create( | |
756 {'name': 'foo-bar', 'alternative': '"fooBar" or "foobar"'}) | |
757 .snippet} (lib/test.html 2 28)' | |
758 ]); | |
759 }); | |
760 | |
761 _testLinter("namespaced attributes don't cause an internal error", { | |
762 'a|lib/test.html': '''<html><body> | |
763 <svg xmlns="http://www.w3.org/2000/svg" width="520" height="350"> | |
764 </svg> | |
765 '''.replaceAll(' ', ''), | |
766 }, []); | |
767 | |
768 group('output logs to file', () { | |
769 final outputLogsPhases = [ | |
770 [ | |
771 new Linter(new TransformOptions( | |
772 injectBuildLogsInOutput: true, releaseMode: false)) | |
773 ] | |
774 ]; | |
775 | |
776 testPhases("logs are output to file", outputLogsPhases, { | |
777 'a|web/test.html': '<!DOCTYPE html><html>\n' | |
778 '<polymer-element name="x-a"></polymer-element>' | |
779 '<script type="application/dart" src="foo.dart">' | |
780 '</script>' | |
781 '<script src="packages/browser/dart.js"></script>' | |
782 '</html>', | |
783 }, { | |
784 'a|web/test.html._buildLogs.1': '{"polymer#3":[{' | |
785 '"level":"Warning",' | |
786 '"message":{' | |
787 '"id":"polymer#3",' | |
788 '"snippet":"${_usePolymerHtmlMessage(0).replaceAll('"','\\"')}"' | |
789 '},' | |
790 '"span":{' | |
791 '"start":{' | |
792 '"url":"web/test.html",' | |
793 '"offset":22,' | |
794 '"line":1,' | |
795 '"column":0' | |
796 '},' | |
797 '"end":{' | |
798 '"url":"web/test.html",' | |
799 '"offset":50,' | |
800 '"line":1,' | |
801 '"column":28' | |
802 '},' | |
803 '"text":"<polymer-element name=\\"x-a\\">"' | |
804 '}' | |
805 '}]}', | |
806 }, [ | |
807 // Logs should still make it to barback too. | |
808 'warning: ${_usePolymerHtmlMessage(0)} (web/test.html 1 0)', | |
809 ]); | |
810 }); | |
811 } | |
812 | |
813 _usePolymerHtmlMessage(int i) { | |
814 var prefix = '../' * i; | |
815 return USE_POLYMER_HTML.create({'reachOutPrefix': prefix}).snippet; | |
816 } | |
817 | |
818 _testLinter(String name, Map inputFiles, List outputMessages, | |
819 [bool solo = false]) { | |
820 var outputFiles = {}; | |
821 if (outputMessages.every((m) => m.startsWith('warning:'))) { | |
822 inputFiles.forEach((k, v) => outputFiles[k] = v); | |
823 } | |
824 if (outputMessages.isEmpty) { | |
825 var linter = new Linter(new TransformOptions()); | |
826 testPhases(name, [[linter]], inputFiles, outputFiles, outputMessages, solo); | |
827 } else { | |
828 testLogOutput((options) => new Linter(options), name, inputFiles, | |
829 outputFiles, outputMessages, solo); | |
830 } | |
831 } | |
OLD | NEW |