| 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.validator_test; |
| 6 |
| 7 import 'package:source_maps/span.dart'; |
| 8 import 'package:polymer/src/validator.dart'; |
| 9 import 'package:unittest/compact_vm_config.dart'; |
| 10 import 'package:unittest/unittest.dart'; |
| 11 |
| 12 import 'transform/common.dart'; |
| 13 |
| 14 void main() { |
| 15 useCompactVMConfiguration(); |
| 16 _testValidator('nothing to report', { |
| 17 'a|web/test.html': '<!DOCTYPE html><html></html>', |
| 18 }, { |
| 19 'a|web/test.html.messages': '', |
| 20 }); |
| 21 |
| 22 group('doctype warning', () { |
| 23 _testValidator('in web', { |
| 24 'a|web/test.html': '<html></html>', |
| 25 }, { |
| 26 'a|web/test.html.messages': |
| 27 'warning: Unexpected start tag (html). Expected DOCTYPE. ' |
| 28 '(web/test.html 0 0)', |
| 29 }); |
| 30 |
| 31 _testValidator('in lib', { |
| 32 'a|lib/test.html': '<html></html>', |
| 33 }, { |
| 34 'a|lib/test.html.messages': '', |
| 35 }); |
| 36 }); |
| 37 |
| 38 group('duplicate polymer-elements,', () { |
| 39 _testValidator('same file', { |
| 40 'a|lib/test.html': '''<html> |
| 41 <polymer-element name="x-a"></polymer-element> |
| 42 <polymer-element name="x-a"></polymer-element> |
| 43 </html>'''.replaceAll(' ', ''), |
| 44 }, { |
| 45 'a|lib/test.html.messages': |
| 46 'warning: duplicate definition for custom tag "x-a". ' |
| 47 '(lib/test.html 1 0)\n' |
| 48 'warning: duplicate definition for custom tag "x-a" ' |
| 49 '(second definition). (lib/test.html 2 0)' |
| 50 }); |
| 51 |
| 52 _testValidator('other file', { |
| 53 'a|lib/b.html': '''<html> |
| 54 <polymer-element name="x-a"></polymer-element> |
| 55 </html>'''.replaceAll(' ', ''), |
| 56 'a|lib/test.html': '''<html> |
| 57 <link rel="import" href="b.html"> |
| 58 <polymer-element name="x-a"></polymer-element> |
| 59 </html>'''.replaceAll(' ', ''), |
| 60 }, { |
| 61 'a|lib/test.html.messages': |
| 62 'warning: duplicate definition for custom tag "x-a". ' |
| 63 '(lib/b.html 1 0)\n' |
| 64 'warning: duplicate definition for custom tag "x-a" ' |
| 65 '(second definition). (lib/test.html 2 0)' |
| 66 }); |
| 67 |
| 68 _testValidator('other package', { |
| 69 'b|lib/b.html': '''<html> |
| 70 <polymer-element name="x-a"></polymer-element> |
| 71 </html>'''.replaceAll(' ', ''), |
| 72 'a|lib/test.html': '''<html> |
| 73 <link rel="import" href="packages/b/b.html"> |
| 74 <polymer-element name="x-a"></polymer-element> |
| 75 </html>'''.replaceAll(' ', ''), |
| 76 }, { |
| 77 'a|lib/test.html.messages': |
| 78 'warning: duplicate definition for custom tag "x-a". ' |
| 79 '(package:b/b.html 1 0)\n' |
| 80 'warning: duplicate definition for custom tag "x-a" ' |
| 81 '(second definition). (lib/test.html 2 0)' |
| 82 }); |
| 83 }); |
| 84 |
| 85 _testValidator('bad link-rel tag (href missing)', { |
| 86 'a|lib/test.html': '''<html> |
| 87 <link rel="import"> |
| 88 <link rel="stylesheet"> |
| 89 <link rel="foo"> |
| 90 <link rel="import" href=""> |
| 91 </html>'''.replaceAll(' ', ''), |
| 92 }, { |
| 93 'a|lib/test.html.messages': |
| 94 'warning: link rel="import" missing href. (lib/test.html 1 0)\n' |
| 95 'warning: link rel="stylesheet" missing href. (lib/test.html 2 0)\n' |
| 96 'warning: link rel="import" missing href. (lib/test.html 4 0)' |
| 97 }); |
| 98 |
| 99 _testValidator('<element> is not supported', { |
| 100 'a|lib/test.html': '''<html> |
| 101 <element name="x-a"></element> |
| 102 </html>'''.replaceAll(' ', ''), |
| 103 }, { |
| 104 'a|lib/test.html.messages': |
| 105 'warning: <element> elements are not supported, use <polymer-element>' |
| 106 ' instead (lib/test.html 1 0)' |
| 107 }); |
| 108 |
| 109 _testValidator('do not nest <polymer-element>', { |
| 110 'a|lib/test.html': '''<html> |
| 111 <polymer-element name="x-a"> |
| 112 <template><div> |
| 113 <polymer-element name="b"></polymer-element> |
| 114 </div></template> |
| 115 </polymer-element> |
| 116 </html>'''.replaceAll(' ', ''), |
| 117 }, { |
| 118 'a|lib/test.html.messages': |
| 119 'error: Nested polymer element definitions are not allowed.' |
| 120 ' (lib/test.html 3 4)' |
| 121 }); |
| 122 |
| 123 _testValidator('need a name for <polymer-element>', { |
| 124 'a|lib/test.html': '''<html> |
| 125 <polymer-element></polymer-element> |
| 126 </html>'''.replaceAll(' ', ''), |
| 127 }, { |
| 128 'a|lib/test.html.messages': |
| 129 'error: Missing tag name of the custom element. Please include an ' |
| 130 'attribute like \'name="your-tag-name"\'. (lib/test.html 1 0)' |
| 131 }); |
| 132 |
| 133 _testValidator('name for <polymer-element> should have dashes', { |
| 134 'a|lib/test.html': '''<html> |
| 135 <polymer-element name="a"></polymer-element> |
| 136 </html>'''.replaceAll(' ', ''), |
| 137 }, { |
| 138 'a|lib/test.html.messages': |
| 139 'error: Invalid name "a". Custom element names must have at least one' |
| 140 ' dash and can\'t be any of the following names: annotation-xml, ' |
| 141 'color-profile, font-face, font-face-src, font-face-uri, ' |
| 142 'font-face-format, font-face-name, missing-glyph. (lib/test.html 1 0)' |
| 143 }); |
| 144 |
| 145 _testValidator('extend is a valid element or existing tag', { |
| 146 'a|lib/test.html': '''<html> |
| 147 <polymer-element name="x-a" extends="li"></polymer-element> |
| 148 </html>'''.replaceAll(' ', ''), |
| 149 }, { |
| 150 'a|lib/test.html.messages': '' |
| 151 }); |
| 152 |
| 153 _testValidator('extend is a valid element or existing tag', { |
| 154 'a|lib/test.html': '''<html> |
| 155 <polymer-element name="x-a" extends="x-b"></polymer-element> |
| 156 </html>'''.replaceAll(' ', ''), |
| 157 }, { |
| 158 'a|lib/test.html.messages': '' |
| 159 'warning: custom element with name "x-b" not found. ' |
| 160 '(lib/test.html 1 0)' |
| 161 }); |
| 162 |
| 163 |
| 164 group('script type matches code', () { |
| 165 _testValidator('top-level, .dart url', { |
| 166 'a|lib/test.html': '''<html> |
| 167 <script src="foo.dart"></script> |
| 168 </html>'''.replaceAll(' ', ''), |
| 169 }, { |
| 170 'a|lib/test.html.messages': |
| 171 'warning: script tag with .dart source file but no type will be ' |
| 172 'treated as JavaScript. Did you forget type="application/dart"?' |
| 173 ' (lib/test.html 1 0)' |
| 174 }); |
| 175 |
| 176 _testValidator('in polymer-element, .dart url', { |
| 177 'a|lib/test.html': '''<html> |
| 178 <polymer-element name="x-a"> |
| 179 <script src="foo.dart"></script> |
| 180 </polymer-element> |
| 181 </html>'''.replaceAll(' ', ''), |
| 182 }, { |
| 183 'a|lib/test.html.messages': |
| 184 'warning: script tag with .dart source file but no type will be ' |
| 185 'treated as JavaScript. Did you forget type="application/dart"?' |
| 186 ' (lib/test.html 2 0)' |
| 187 }); |
| 188 |
| 189 _testValidator('in polymer-element, .js url', { |
| 190 'a|lib/test.html': '''<html> |
| 191 <polymer-element name="x-a"> |
| 192 <script src="foo.js"></script> |
| 193 </polymer-element> |
| 194 </html>'''.replaceAll(' ', ''), |
| 195 }, { |
| 196 'a|lib/test.html.messages': '' |
| 197 }); |
| 198 |
| 199 _testValidator('in polymer-element, inlined', { |
| 200 'a|lib/test.html': '''<html> |
| 201 <polymer-element name="x-a"> |
| 202 <script>foo...</script> |
| 203 </polymer-element> |
| 204 </html>'''.replaceAll(' ', ''), |
| 205 }, { |
| 206 'a|lib/test.html.messages': |
| 207 'warning: script tag in polymer element with no type will ' |
| 208 'be treated as JavaScript. Did you forget type="application/dart"?' |
| 209 ' (lib/test.html 2 0)' |
| 210 }); |
| 211 |
| 212 _testValidator('top-level, dart type & .dart url', { |
| 213 'a|lib/test.html': '''<html> |
| 214 <script type="applicatino/dart" src="foo.dart"></script> |
| 215 </html>'''.replaceAll(' ', ''), |
| 216 }, { |
| 217 'a|lib/test.html.messages': '' |
| 218 }); |
| 219 |
| 220 _testValidator('top-level, dart type & .js url', { |
| 221 'a|lib/test.html': '''<html> |
| 222 <script type="application/dart" src="foo.js"></script> |
| 223 </html>'''.replaceAll(' ', ''), |
| 224 }, { |
| 225 'a|lib/test.html.messages': |
| 226 'warning: "application/dart" scripts should use the .dart file ' |
| 227 'extension. (lib/test.html 1 0)' |
| 228 }); |
| 229 }); |
| 230 |
| 231 _testValidator('script tags should have only src url or inline code', { |
| 232 'a|lib/test.html': '''<html> |
| 233 <script type="application/dart" src="foo.dart">more</script> |
| 234 </html>'''.replaceAll(' ', ''), |
| 235 }, { |
| 236 'a|lib/test.html.messages': |
| 237 'warning: script tag has "src" attribute and also has script text. ' |
| 238 '(lib/test.html 1 0)' |
| 239 }); |
| 240 |
| 241 group('event handlers', () { |
| 242 _testValidator('onfoo is not polymer', { |
| 243 'a|lib/test.html': '''<html><body> |
| 244 <div onfoo="something"></div> |
| 245 '''.replaceAll(' ', ''), |
| 246 }, { |
| 247 'a|lib/test.html.messages': |
| 248 'warning: Event handler "onfoo" will be interpreted as an inline ' |
| 249 'JavaScript event handler. Use the form ' |
| 250 'on-event-name="handlerName" if you want a Dart handler ' |
| 251 'that will automatically update the UI based on model changes. ' |
| 252 '(lib/test.html 1 0)' |
| 253 }); |
| 254 |
| 255 _testValidator('on-foo is only supported in polymer elements', { |
| 256 'a|lib/test.html': '''<html><body> |
| 257 <div on-foo="something"></div> |
| 258 '''.replaceAll(' ', ''), |
| 259 }, { |
| 260 'a|lib/test.html.messages': |
| 261 'warning: Inline event handlers are only supported inside ' |
| 262 'declarations of <polymer-element>. ' |
| 263 '(lib/test.html 1 0)' |
| 264 }); |
| 265 |
| 266 _testValidator('on-foo is not an expression', { |
| 267 'a|lib/test.html': '''<html><body> |
| 268 <polymer-element name="x-a"><div on-foo="bar()"></div> |
| 269 </polymer-element> |
| 270 '''.replaceAll(' ', ''), |
| 271 }, { |
| 272 'a|lib/test.html.messages': |
| 273 'warning: Invalid event handler body "bar()". Declare a method ' |
| 274 'in your custom element "void handlerName(event, detail, target)" ' |
| 275 'and use the form on-foo="handlerName". ' |
| 276 '(lib/test.html 1 28)' |
| 277 }); |
| 278 }); |
| 279 |
| 280 group('using custom tags', () { |
| 281 _testValidator('tag exists (x-tag)', { |
| 282 'a|lib/test.html': '<x-foo></x-foo>', |
| 283 }, { |
| 284 'a|lib/test.html.messages': |
| 285 'warning: definition for custom element with tag name "x-foo" not ' |
| 286 'found. (lib/test.html 0 0)' |
| 287 }); |
| 288 |
| 289 _testValidator('tag exists (type extension)', { |
| 290 'a|lib/test.html': '<div is="x-foo"></div>', |
| 291 }, { |
| 292 'a|lib/test.html.messages': |
| 293 'warning: definition for custom element with tag name "x-foo" not ' |
| 294 'found. (lib/test.html 0 0)' |
| 295 }); |
| 296 |
| 297 _testValidator('used correctly (no base tag)', { |
| 298 'a|lib/test.html': ''' |
| 299 <polymer-element name="x-a"></polymer-element> |
| 300 <x-a></x-a> |
| 301 '''.replaceAll(' ', ''), |
| 302 }, { |
| 303 'a|lib/test.html.messages': '' |
| 304 }); |
| 305 |
| 306 _testValidator('used incorrectly (no base tag)', { |
| 307 'a|lib/test.html': ''' |
| 308 <polymer-element name="x-a"></polymer-element> |
| 309 <div is="x-a"></div> |
| 310 '''.replaceAll(' ', ''), |
| 311 }, { |
| 312 'a|lib/test.html.messages': |
| 313 'warning: custom element "x-a" doesn\'t declare any type ' |
| 314 'extensions. To fix this, either rewrite this tag as ' |
| 315 '<x-a> or add \'extends="div"\' to ' |
| 316 'the custom element declaration. (lib/test.html 1 0)' |
| 317 }); |
| 318 |
| 319 _testValidator('used incorrectly, imported def (no base tag)', { |
| 320 'a|lib/b.html': '<polymer-element name="x-a"></polymer-element>', |
| 321 'a|lib/test.html': ''' |
| 322 <link rel="import" href="b.html"> |
| 323 <div is="x-a"></div> |
| 324 '''.replaceAll(' ', ''), |
| 325 }, { |
| 326 'a|lib/test.html.messages': |
| 327 'warning: custom element "x-a" doesn\'t declare any type ' |
| 328 'extensions. To fix this, either rewrite this tag as ' |
| 329 '<x-a> or add \'extends="div"\' to ' |
| 330 'the custom element declaration. (lib/test.html 1 0)' |
| 331 }); |
| 332 |
| 333 _testValidator('used correctly (base tag)', { |
| 334 'a|lib/b.html': ''' |
| 335 <polymer-element name="x-a" extends="div"> |
| 336 </polymer-element> |
| 337 '''.replaceAll(' ', ''), |
| 338 'a|lib/test.html': ''' |
| 339 <link rel="import" href="b.html"> |
| 340 <div is="x-a"></div> |
| 341 '''.replaceAll(' ', ''), |
| 342 }, { |
| 343 'a|lib/test.html.messages': '' |
| 344 }); |
| 345 |
| 346 _testValidator('used incorrectly (missing base tag)', { |
| 347 'a|lib/b.html': ''' |
| 348 <polymer-element name="x-a" extends="div"> |
| 349 </polymer-element> |
| 350 '''.replaceAll(' ', ''), |
| 351 'a|lib/test.html': ''' |
| 352 <link rel="import" href="b.html"> |
| 353 <x-a></x-a> |
| 354 '''.replaceAll(' ', ''), |
| 355 }, { |
| 356 'a|lib/test.html.messages': '' |
| 357 'warning: custom element "x-a" extends from "div", but this tag ' |
| 358 'will not include the default properties of "div". To fix this, ' |
| 359 'either write this tag as <div is="x-a"> or remove the "extends" ' |
| 360 'attribute from the custom element declaration. (lib/test.html 1 0)' |
| 361 }); |
| 362 |
| 363 _testValidator('used incorrectly (wrong base tag)', { |
| 364 'a|lib/b.html': ''' |
| 365 <polymer-element name="x-a" extends="div"> |
| 366 </polymer-element> |
| 367 '''.replaceAll(' ', ''), |
| 368 'a|lib/test.html': ''' |
| 369 <link rel="import" href="b.html"> |
| 370 <span is="x-a"></span> |
| 371 '''.replaceAll(' ', ''), |
| 372 }, { |
| 373 'a|lib/test.html.messages': '' |
| 374 'warning: custom element "x-a" extends from "div". Did you mean ' |
| 375 'to write <div is="x-a">? (lib/test.html 1 0)' |
| 376 }); |
| 377 |
| 378 _testValidator('used incorrectly (wrong base tag, transitive)', { |
| 379 'a|lib/c.html': ''' |
| 380 <polymer-element name="x-c" extends="li"> |
| 381 </polymer-element> |
| 382 <polymer-element name="x-b" extends="x-c"> |
| 383 </polymer-element> |
| 384 '''.replaceAll(' ', ''), |
| 385 'a|lib/b.html': ''' |
| 386 <link rel="import" href="c.html"> |
| 387 <polymer-element name="x-a" extends="x-b"> |
| 388 </polymer-element> |
| 389 '''.replaceAll(' ', ''), |
| 390 'a|lib/test.html': ''' |
| 391 <link rel="import" href="b.html"> |
| 392 <span is="x-a"></span> |
| 393 '''.replaceAll(' ', ''), |
| 394 }, { |
| 395 'a|lib/test.html.messages': '' |
| 396 'warning: custom element "x-a" extends from "li". Did you mean ' |
| 397 'to write <li is="x-a">? (lib/test.html 1 0)' |
| 398 }); |
| 399 }); |
| 400 } |
| 401 |
| 402 _testValidator(String name, Map inputFiles, Map outputMessages) { |
| 403 var validator = new Validator(_testFormatter); |
| 404 var outputFiles = {}; |
| 405 inputFiles.forEach((k, v) => outputFiles[k] = v); |
| 406 outputMessages.forEach((k, v) => outputFiles[k] = v); |
| 407 var keys = inputFiles.keys.toSet(); |
| 408 keys.retainAll(outputMessages.keys); |
| 409 expect(keys, isEmpty); |
| 410 testPhases(name, [[validator]], inputFiles, outputFiles); |
| 411 } |
| 412 |
| 413 |
| 414 _testFormatter(String kind, String message, Span span) { |
| 415 var formattedMessage = '$kind: $message'; |
| 416 if (span != null) { |
| 417 formattedMessage = '$formattedMessage ' |
| 418 '(${span.sourceUrl} ${span.start.line} ${span.start.column})'; |
| 419 } |
| 420 return formattedMessage; |
| 421 } |
| OLD | NEW |