| Index: tests/html/node_validator_test.dart | 
| diff --git a/tests/html/node_validator_test.dart b/tests/html/node_validator_test.dart | 
| index 045a2b8a3d4faceb224521e09a995b61b217fe38..71ab679157adca2b2aa52428c79c5d15419f15fa 100644 | 
| --- a/tests/html/node_validator_test.dart | 
| +++ b/tests/html/node_validator_test.dart | 
| @@ -186,229 +186,228 @@ main() { | 
| ['s']); | 
| }); | 
|  | 
| -  group('NodeValidationPolicy', () { | 
| +  group('allowNavigation', () { | 
| +    var validator = new NodeValidatorBuilder()..allowNavigation(); | 
|  | 
| -    group('allowNavigation', () { | 
| -      var validator = new NodeValidatorBuilder()..allowNavigation(); | 
| - | 
| -      testHtml('allows anchor tags', | 
| -          validator, | 
| -          '<a href="#foo">foo</a>'); | 
| - | 
| -      testHtml('allows form elements', | 
| -          validator, | 
| -          '<form method="post" action="/foo"></form>'); | 
| - | 
| -      testHtml('disallows script navigation', | 
| -          validator, | 
| -          '<a href="javascript:foo = 1">foo</a>', | 
| -          '<a>foo</a>'); | 
| - | 
| -      testHtml('disallows cross-site navigation', | 
| -          validator, | 
| -          '<a href="http://example.com">example.com</a>', | 
| -          '<a>example.com</a>'); | 
| +    testHtml('allows anchor tags', | 
| +        validator, | 
| +        '<a href="#foo">foo</a>'); | 
|  | 
| -      testHtml('blocks other elements', | 
| -          validator, | 
| -          '<a href="#foo"><b>foo</b></a>', | 
| -          '<a href="#foo"></a>'); | 
| +    testHtml('allows form elements', | 
| +        validator, | 
| +        '<form method="post" action="/foo"></form>'); | 
|  | 
| -      testHtml('blocks tag extension', | 
| -          validator, | 
| -          '<a is="x-foo"></a>', | 
| -          ''); | 
| -    }); | 
| +    testHtml('disallows script navigation', | 
| +        validator, | 
| +        '<a href="javascript:foo = 1">foo</a>', | 
| +        '<a>foo</a>'); | 
|  | 
| -    group('allowImages', () { | 
| -      var validator = new NodeValidatorBuilder()..allowImages(); | 
| +    testHtml('disallows cross-site navigation', | 
| +        validator, | 
| +        '<a href="http://example.com">example.com</a>', | 
| +        '<a>example.com</a>'); | 
|  | 
| -      testHtml('allows images', | 
| -          validator, | 
| -          '<img src="/foo.jpg" alt="something" width="100" height="100"/>'); | 
| +    testHtml('blocks other elements', | 
| +        validator, | 
| +        '<a href="#foo"><b>foo</b></a>', | 
| +        '<a href="#foo"></a>'); | 
|  | 
| -      testHtml('blocks onerror', | 
| -          validator, | 
| -          '<img src="/foo.jpg" onerror="something"/>', | 
| -          '<img src="/foo.jpg"/>'); | 
| +    testHtml('blocks tag extension', | 
| +        validator, | 
| +        '<a is="x-foo"></a>', | 
| +        ''); | 
| +  }); | 
|  | 
| -      testHtml('enforces same-origin', | 
| -          validator, | 
| -          '<img src="http://example.com/foo.jpg"/>', | 
| -          '<img/>'); | 
| -    }); | 
| +  group('allowImages', () { | 
| +    var validator = new NodeValidatorBuilder()..allowImages(); | 
|  | 
| -    group('allowCustomElement', () { | 
| -      var validator = new NodeValidatorBuilder() | 
| -        ..allowCustomElement( | 
| -            'x-foo', | 
| -            attributes: ['bar'], | 
| -            uriAttributes: ['baz']) | 
| -        ..allowHtml5(); | 
| +    testHtml('allows images', | 
| +        validator, | 
| +        '<img src="/foo.jpg" alt="something" width="100" height="100"/>'); | 
|  | 
| -      testHtml('allows custom elements', | 
| -          validator, | 
| -          '<x-foo bar="something" baz="/foo.jpg"></x-foo>'); | 
| +    testHtml('blocks onerror', | 
| +        validator, | 
| +        '<img src="/foo.jpg" onerror="something"/>', | 
| +        '<img src="/foo.jpg"/>'); | 
|  | 
| +    testHtml('enforces same-origin', | 
| +        validator, | 
| +        '<img src="http://example.com/foo.jpg"/>', | 
| +        '<img/>'); | 
| +  }); | 
|  | 
| -      testHtml('validates custom tag URIs', | 
| -          validator, | 
| -          '<x-foo baz="http://example.com/foo.jpg"></x-foo>', | 
| -          '<x-foo></x-foo>'); | 
| +  group('allowCustomElement', () { | 
| +    var validator = new NodeValidatorBuilder() | 
| +      ..allowCustomElement( | 
| +          'x-foo', | 
| +          attributes: ['bar'], | 
| +          uriAttributes: ['baz']) | 
| +      ..allowHtml5(); | 
|  | 
| -      testHtml('blocks type extensions', | 
| -          validator, | 
| -          '<div is="x-foo"></div>', | 
| -          ''); | 
| +    testHtml('allows custom elements', | 
| +        validator, | 
| +        '<x-foo bar="something" baz="/foo.jpg"></x-foo>'); | 
|  | 
| -      testHtml('blocks tags on non-matching elements', | 
| -          validator, | 
| -          '<div bar="foo"></div>', | 
| -          '<div></div>'); | 
| -    }); | 
|  | 
| -    group('allowTagExtension', () { | 
| -       var validator = new NodeValidatorBuilder() | 
| -        ..allowTagExtension( | 
| -            'x-foo', | 
| -            'div', | 
| -            attributes: ['bar'], | 
| -            uriAttributes: ['baz']) | 
| -        ..allowHtml5(); | 
| +    testHtml('validates custom tag URIs', | 
| +        validator, | 
| +        '<x-foo baz="http://example.com/foo.jpg"></x-foo>', | 
| +        '<x-foo></x-foo>'); | 
|  | 
| -      testHtml('allows tag extensions', | 
| -          validator, | 
| -          '<div is="x-foo" bar="something" baz="/foo.jpg"></div>'); | 
| +    testHtml('blocks type extensions', | 
| +        validator, | 
| +        '<div is="x-foo"></div>', | 
| +        ''); | 
|  | 
| -      testHtml('blocks custom elements', | 
| -            validator, | 
| -            '<x-foo></x-foo>', | 
| -            ''); | 
| +    testHtml('blocks tags on non-matching elements', | 
| +        validator, | 
| +        '<div bar="foo"></div>', | 
| +        '<div></div>'); | 
| +  }); | 
|  | 
| -      testHtml('validates tag extension URIs', | 
| -          validator, | 
| -          '<div is="x-foo" baz="http://example.com/foo.jpg"></div>', | 
| -          '<div is="x-foo"></div>'); | 
| +  group('allowTagExtension', () { | 
| +     var validator = new NodeValidatorBuilder() | 
| +      ..allowTagExtension( | 
| +          'x-foo', | 
| +          'div', | 
| +          attributes: ['bar'], | 
| +          uriAttributes: ['baz']) | 
| +      ..allowHtml5(); | 
|  | 
| -      testHtml('blocks tags on non-matching elements', | 
| -          validator, | 
| -          '<div bar="foo"></div>', | 
| -          '<div></div>'); | 
| +    testHtml('allows tag extensions', | 
| +        validator, | 
| +        '<div is="x-foo" bar="something" baz="/foo.jpg"></div>'); | 
|  | 
| -      testHtml('blocks non-matching tags', | 
| +    testHtml('blocks custom elements', | 
| validator, | 
| -          '<span is="x-foo">something</span>', | 
| +          '<x-foo></x-foo>', | 
| ''); | 
|  | 
| -      validator = new NodeValidatorBuilder() | 
| -        ..allowTagExtension( | 
| -            'x-foo', | 
| -            'div', | 
| -            attributes: ['bar'], | 
| -            uriAttributes: ['baz']) | 
| -        ..allowTagExtension( | 
| -            'x-else', | 
| -            'div'); | 
| - | 
| -      testHtml('blocks tags on non-matching custom elements', | 
| -          validator, | 
| -          '<div bar="foo" is="x-else"></div>', | 
| -          '<div is="x-else"></div>'); | 
| -    }); | 
| - | 
| -    group('allowTemplating', () { | 
| -      var validator = new NodeValidatorBuilder() | 
| -        ..allowTemplating() | 
| -        ..allowHtml5(); | 
| +    testHtml('validates tag extension URIs', | 
| +        validator, | 
| +        '<div is="x-foo" baz="http://example.com/foo.jpg"></div>', | 
| +        '<div is="x-foo"></div>'); | 
|  | 
| -      testHtml('allows templates', | 
| -          validator, | 
| -          '<template bind="{{a}}"></template>'); | 
| +    testHtml('blocks tags on non-matching elements', | 
| +        validator, | 
| +        '<div bar="foo"></div>', | 
| +        '<div></div>'); | 
|  | 
| -      testHtml('allows template attributes', | 
| -          validator, | 
| -          '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"></template>'); | 
| +    testHtml('blocks non-matching tags', | 
| +        validator, | 
| +        '<span is="x-foo">something</span>', | 
| +        ''); | 
|  | 
| -      testHtml('allows template attribute', | 
| -          validator, | 
| -          '<div template repeat="{{}}"></div>'); | 
| +    validator = new NodeValidatorBuilder() | 
| +      ..allowTagExtension( | 
| +          'x-foo', | 
| +          'div', | 
| +          attributes: ['bar'], | 
| +          uriAttributes: ['baz']) | 
| +      ..allowTagExtension( | 
| +          'x-else', | 
| +          'div'); | 
| + | 
| +    testHtml('blocks tags on non-matching custom elements', | 
| +        validator, | 
| +        '<div bar="foo" is="x-else"></div>', | 
| +        '<div is="x-else"></div>'); | 
| +  }); | 
|  | 
| -      testHtml('blocks illegal template attribute', | 
| -          validator, | 
| -          '<div template="foo" repeat="{{}}"></div>', | 
| -          '<div></div>'); | 
| -    }); | 
| +  group('allowTemplating', () { | 
| +    var validator = new NodeValidatorBuilder() | 
| +      ..allowTemplating() | 
| +      ..allowHtml5(); | 
|  | 
| -    group('allowSvg', () { | 
| -      var validator = new NodeValidatorBuilder()..allowSvg(); | 
| +    testHtml('allows templates', | 
| +        validator, | 
| +        '<template bind="{{a}}"></template>'); | 
|  | 
| -      testHtml('allows basic SVG', | 
| +    testHtml('allows template attributes', | 
| validator, | 
| -        '<svg xmlns="http://www.w3.org/2000/svg' | 
| -            'xmlns:xlink="http://www.w3.org/1999/xlink">' | 
| -          '<image xlink:href="foo" data-foo="bar"/>' | 
| -        '</svg>'); | 
| +        '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"></template>'); | 
|  | 
| -      testHtml('blocks script elements', | 
| +    testHtml('allows template attribute', | 
| validator, | 
| -        '<svg xmlns="http://www.w3.org/2000/svg>' | 
| -          '<script></script>' | 
| -        '</svg>', | 
| -        '<svg xmlns="http://www.w3.org/2000/svg></svg>'); | 
| +        '<div template repeat="{{}}"></div>'); | 
|  | 
| -      testHtml('blocks script handlers', | 
| +    testHtml('blocks illegal template attribute', | 
| validator, | 
| -        '<svg xmlns="http://www.w3.org/2000/svg' | 
| -            'xmlns:xlink="http://www.w3.org/1999/xlink">' | 
| -          '<image xlink:href="foo" onerror="something"/>' | 
| -        '</svg>', | 
| -        '<svg xmlns="http://www.w3.org/2000/svg' | 
| -            'xmlns:xlink="http://www.w3.org/1999/xlink">' | 
| -          '<image xlink:href="foo"/>' | 
| -        '</svg>'); | 
| - | 
| -      testHtml('blocks foreignObject content', | 
| -        validator, | 
| -        '<svg xmlns="http://www.w3.org/2000/svg">' | 
| -          '<foreignobject width="100" height="150">' | 
| -            '<body xmlns="http://www.w3.org/1999/xhtml">' | 
| -              '<div>Some content</div>' | 
| -            '</body>' | 
| -          '</foreignobject>' | 
| -          '<number>42</number>' | 
| -        '</svg>', | 
| -        '<svg xmlns="http://www.w3.org/2000/svg">' | 
| -          '<number>42</number>' | 
| -        '</svg>'); | 
| -    }); | 
| +        '<div template="foo" repeat="{{}}"></div>', | 
| +        '<div></div>'); | 
| +  }); | 
|  | 
| -    group('allowInlineStyles', () { | 
| -      var validator = new NodeValidatorBuilder() | 
| -          ..allowTextElements() | 
| -          ..allowInlineStyles(); | 
| +  group('allowSvg', () { | 
| +    var validator = new NodeValidatorBuilder() | 
| +      ..allowSvg() | 
| +      ..allowTextElements(); | 
| + | 
| +    testHtml('allows basic SVG', | 
| +      validator, | 
| +      '<svg xmlns="http://www.w3.org/2000/svg' | 
| +          'xmlns:xlink="http://www.w3.org/1999/xlink">' | 
| +        '<image xlink:href="foo" data-foo="bar"/>' | 
| +      '</svg>'); | 
| + | 
| +    testHtml('blocks script elements', | 
| +      validator, | 
| +      '<svg xmlns="http://www.w3.org/2000/svg>' | 
| +        '<script></script>' | 
| +      '</svg>', | 
| +      '<svg xmlns="http://www.w3.org/2000/svg></svg>'); | 
| + | 
| +    testHtml('blocks script handlers', | 
| +      validator, | 
| +      '<svg xmlns="http://www.w3.org/2000/svg' | 
| +          'xmlns:xlink="http://www.w3.org/1999/xlink">' | 
| +        '<image xlink:href="foo" onerror="something"/>' | 
| +      '</svg>', | 
| +      '<svg xmlns="http://www.w3.org/2000/svg' | 
| +          'xmlns:xlink="http://www.w3.org/1999/xlink">' | 
| +        '<image xlink:href="foo"/>' | 
| +      '</svg>'); | 
| + | 
| +    testHtml('blocks foreignObject content', | 
| +      validator, | 
| +      '<svg xmlns="http://www.w3.org/2000/svg">' | 
| +        '<foreignobject width="100" height="150">' | 
| +          '<body xmlns="http://www.w3.org/1999/xhtml">' | 
| +            '<div>Some content</div>' | 
| +          '</body>' | 
| +        '</foreignobject>' | 
| +        '<b>42</b>' | 
| +      '</svg>', | 
| +      '<svg xmlns="http://www.w3.org/2000/svg">' | 
| +        '<b>42</b>' | 
| +      '</svg>'); | 
| +  }); | 
|  | 
| -      testHtml('allows inline styles', | 
| -          validator, | 
| -          '<span style="background-color:red">text</span>'); | 
| +  group('allowInlineStyles', () { | 
| +    var validator = new NodeValidatorBuilder() | 
| +        ..allowTextElements() | 
| +        ..allowInlineStyles(); | 
|  | 
| -      testHtml('blocks other attributes', | 
| -          validator, | 
| -          '<span class="red-span"></span>', | 
| -          '<span></span>'); | 
| +    testHtml('allows inline styles', | 
| +        validator, | 
| +        '<span style="background-color:red">text</span>'); | 
|  | 
| -      validator = new NodeValidatorBuilder() | 
| -          ..allowTextElements() | 
| -          ..allowInlineStyles(tagName: 'span'); | 
| +    testHtml('blocks other attributes', | 
| +        validator, | 
| +        '<span class="red-span"></span>', | 
| +        '<span></span>'); | 
|  | 
| -      testHtml('scoped allows inline styles on spans', | 
| -          validator, | 
| -          '<span style="background-color:red">text</span>'); | 
| +    validator = new NodeValidatorBuilder() | 
| +        ..allowTextElements() | 
| +        ..allowInlineStyles(tagName: 'span'); | 
|  | 
| -      testHtml('scoped blocks inline styles on LIs', | 
| -          validator, | 
| -          '<li style="background-color:red">text</li>', | 
| -          '<li>text</li>'); | 
| -    }); | 
| +    testHtml('scoped allows inline styles on spans', | 
| +        validator, | 
| +        '<span style="background-color:red">text</span>'); | 
| + | 
| +    testHtml('scoped blocks inline styles on LIs', | 
| +        validator, | 
| +        '<li style="background-color:red">text</li>', | 
| +        '<li>text</li>'); | 
| }); | 
|  | 
| group('throws', () { | 
|  |