|  | // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | library SvgElementTest; | 
|  |  | 
|  | import 'dart:html'; | 
|  | import 'dart:svg' as svg; | 
|  | import 'package:expect/expect.dart'; | 
|  | import 'package:unittest/html_individual_config.dart'; | 
|  | import 'package:unittest/unittest.dart'; | 
|  |  | 
|  | main() { | 
|  | useHtmlIndividualConfiguration(); | 
|  |  | 
|  | var isSvgSvgElement = | 
|  | predicate((x) => x is svg.SvgSvgElement, 'is a SvgSvgElement'); | 
|  |  | 
|  | List<String> _nodeStrings(Iterable<Node> input) { | 
|  | final out = new List<String>(); | 
|  | for (Node n in input) { | 
|  | if (n is Element) { | 
|  | Element e = n; | 
|  | out.add(e.tagName); | 
|  | } else { | 
|  | out.add(n.text); | 
|  | } | 
|  | } | 
|  | return out; | 
|  | } | 
|  |  | 
|  | ; | 
|  |  | 
|  | testConstructor(String tagName, Function isExpectedClass, | 
|  | [bool expectation = true, allowsInnerHtml = true]) { | 
|  | test(tagName, () { | 
|  | expect(isExpectedClass(new svg.SvgElement.tag(tagName)), expectation); | 
|  | if (allowsInnerHtml) { | 
|  | expect(isExpectedClass(new svg.SvgElement.svg('<$tagName></$tagName>')), | 
|  | expectation && allowsInnerHtml); | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  | group('additionalConstructors', () { | 
|  | test('valid', () { | 
|  | final svgContent = "<svg version=\"1.1\">\n" | 
|  | "  <circle></circle>\n" | 
|  | "  <path></path>\n" | 
|  | "</svg>"; | 
|  | final el = new svg.SvgElement.svg(svgContent); | 
|  | expect(el, isSvgSvgElement); | 
|  | expect( | 
|  | el.innerHtml, | 
|  | anyOf( | 
|  | "<circle></circle><path></path>", | 
|  | '<circle ' | 
|  | 'xmlns="http://www.w3.org/2000/svg" /><path ' | 
|  | 'xmlns="http://www.w3.org/2000/svg" />')); | 
|  | expect( | 
|  | el.outerHtml, | 
|  | anyOf( | 
|  | svgContent, | 
|  | '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">\n  ' | 
|  | '<circle />\n  <path />\n</svg>')); | 
|  | }); | 
|  |  | 
|  | test('has no parent', | 
|  | () => expect(new svg.SvgElement.svg('<circle/>').parent, isNull)); | 
|  |  | 
|  | test('empty', () { | 
|  | expect(() => new svg.SvgElement.svg(""), throwsStateError); | 
|  | }); | 
|  |  | 
|  | test('too many elements', () { | 
|  | expect(() => new svg.SvgElement.svg("<circle></circle><path></path>"), | 
|  | throwsStateError); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | // Unfortunately, because the filtering mechanism in unittest is a regex done | 
|  | group('supported_animate', () { | 
|  | test('supported', () { | 
|  | expect(svg.AnimateElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_animateMotion', () { | 
|  | test('supported', () { | 
|  | expect(svg.AnimateMotionElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_animateTransform', () { | 
|  | test('supported', () { | 
|  | expect(svg.AnimateTransformElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feBlend', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEBlendElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feColorMatrix', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEColorMatrixElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feComponentTransfer', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEComponentTransferElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feConvolveMatrix', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEConvolveMatrixElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feDiffuseLighting', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEDiffuseLightingElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feDisplacementMap', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEDisplacementMapElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feDistantLight', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEDistantLightElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feFlood', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEFloodElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feFuncA', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEFuncAElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feFuncB', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEFuncBElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feFuncG', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEFuncGElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feFuncR', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEFuncRElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feGaussianBlur', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEGaussianBlurElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feImage', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEImageElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feMerge', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEMergeElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feMergeNode', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEMergeNodeElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feOffset', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEOffsetElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feComponentTransfer', () { | 
|  | test('supported', () { | 
|  | expect(svg.FEPointLightElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feSpecularLighting', () { | 
|  | test('supported', () { | 
|  | expect(svg.FESpecularLightingElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feComponentTransfer', () { | 
|  | test('supported', () { | 
|  | expect(svg.FESpotLightElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feTile', () { | 
|  | test('supported', () { | 
|  | expect(svg.FETileElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_feTurbulence', () { | 
|  | test('supported', () { | 
|  | expect(svg.FETurbulenceElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_filter', () { | 
|  | test('supported', () { | 
|  | expect(svg.FilterElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_foreignObject', () { | 
|  | test('supported', () { | 
|  | expect(svg.ForeignObjectElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('supported_set', () { | 
|  | test('supported', () { | 
|  | expect(svg.SetElement.supported, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('constructors', () { | 
|  | testConstructor('a', (e) => e is svg.AElement); | 
|  | testConstructor('circle', (e) => e is svg.CircleElement); | 
|  | testConstructor('clipPath', (e) => e is svg.ClipPathElement); | 
|  | testConstructor('defs', (e) => e is svg.DefsElement); | 
|  | testConstructor('desc', (e) => e is svg.DescElement); | 
|  | testConstructor('ellipse', (e) => e is svg.EllipseElement); | 
|  | testConstructor('g', (e) => e is svg.GElement); | 
|  | testConstructor('image', (e) => e is svg.ImageElement); | 
|  | testConstructor('line', (e) => e is svg.LineElement); | 
|  | testConstructor('linearGradient', (e) => e is svg.LinearGradientElement); | 
|  | testConstructor('marker', (e) => e is svg.MarkerElement); | 
|  | testConstructor('mask', (e) => e is svg.MaskElement); | 
|  | testConstructor('path', (e) => e is svg.PathElement); | 
|  | testConstructor('pattern', (e) => e is svg.PatternElement); | 
|  | testConstructor('polygon', (e) => e is svg.PolygonElement); | 
|  | testConstructor('polyline', (e) => e is svg.PolylineElement); | 
|  | testConstructor('radialGradient', (e) => e is svg.RadialGradientElement); | 
|  | testConstructor('rect', (e) => e is svg.RectElement); | 
|  | test('script', () { | 
|  | expect(new svg.SvgElement.tag('script') is svg.ScriptElement, isTrue); | 
|  | }); | 
|  | testConstructor('stop', (e) => e is svg.StopElement); | 
|  | testConstructor('style', (e) => e is svg.StyleElement); | 
|  | testConstructor('switch', (e) => e is svg.SwitchElement); | 
|  | testConstructor('symbol', (e) => e is svg.SymbolElement); | 
|  | testConstructor('tspan', (e) => e is svg.TSpanElement); | 
|  | testConstructor('text', (e) => e is svg.TextElement); | 
|  | testConstructor('textPath', (e) => e is svg.TextPathElement); | 
|  | testConstructor('title', (e) => e is svg.TitleElement); | 
|  | testConstructor('use', (e) => e is svg.UseElement); | 
|  | testConstructor('view', (e) => e is svg.ViewElement); | 
|  | // TODO(alanknight): Issue 23144 | 
|  | testConstructor('animate', (e) => e is svg.AnimateElement, | 
|  | svg.AnimateElement.supported); | 
|  | testConstructor('animateMotion', (e) => e is svg.AnimateMotionElement, | 
|  | svg.AnimateMotionElement.supported); | 
|  | testConstructor('animateTransform', (e) => e is svg.AnimateTransformElement, | 
|  | svg.AnimateTransformElement.supported); | 
|  | testConstructor('feBlend', (e) => e is svg.FEBlendElement, | 
|  | svg.FEBlendElement.supported); | 
|  | testConstructor('feColorMatrix', (e) => e is svg.FEColorMatrixElement, | 
|  | svg.FEColorMatrixElement.supported); | 
|  | testConstructor( | 
|  | 'feComponentTransfer', | 
|  | (e) => e is svg.FEComponentTransferElement, | 
|  | svg.FEComponentTransferElement.supported); | 
|  | testConstructor('feConvolveMatrix', (e) => e is svg.FEConvolveMatrixElement, | 
|  | svg.FEConvolveMatrixElement.supported); | 
|  | testConstructor( | 
|  | 'feDiffuseLighting', | 
|  | (e) => e is svg.FEDiffuseLightingElement, | 
|  | svg.FEDiffuseLightingElement.supported); | 
|  | testConstructor( | 
|  | 'feDisplacementMap', | 
|  | (e) => e is svg.FEDisplacementMapElement, | 
|  | svg.FEDisplacementMapElement.supported); | 
|  | testConstructor('feDistantLight', (e) => e is svg.FEDistantLightElement, | 
|  | svg.FEDistantLightElement.supported); | 
|  | testConstructor('feFlood', (e) => e is svg.FEFloodElement, | 
|  | svg.FEFloodElement.supported); | 
|  | testConstructor('feFuncA', (e) => e is svg.FEFuncAElement, | 
|  | svg.FEFuncAElement.supported); | 
|  | testConstructor('feFuncB', (e) => e is svg.FEFuncBElement, | 
|  | svg.FEFuncBElement.supported); | 
|  | testConstructor('feFuncG', (e) => e is svg.FEFuncGElement, | 
|  | svg.FEFuncGElement.supported); | 
|  | testConstructor('feFuncR', (e) => e is svg.FEFuncRElement, | 
|  | svg.FEFuncRElement.supported); | 
|  | testConstructor('feGaussianBlur', (e) => e is svg.FEGaussianBlurElement, | 
|  | svg.FEGaussianBlurElement.supported); | 
|  | testConstructor('feImage', (e) => e is svg.FEImageElement, | 
|  | svg.FEImageElement.supported); | 
|  | testConstructor('feMerge', (e) => e is svg.FEMergeElement, | 
|  | svg.FEMergeElement.supported); | 
|  | testConstructor('feMergeNode', (e) => e is svg.FEMergeNodeElement, | 
|  | svg.FEMergeNodeElement.supported); | 
|  | testConstructor('feOffset', (e) => e is svg.FEOffsetElement, | 
|  | svg.FEOffsetElement.supported); | 
|  | testConstructor('fePointLight', (e) => e is svg.FEPointLightElement, | 
|  | svg.FEPointLightElement.supported); | 
|  | testConstructor( | 
|  | 'feSpecularLighting', | 
|  | (e) => e is svg.FESpecularLightingElement, | 
|  | svg.FESpecularLightingElement.supported); | 
|  | testConstructor('feSpotLight', (e) => e is svg.FESpotLightElement, | 
|  | svg.FESpotLightElement.supported); | 
|  | testConstructor( | 
|  | 'feTile', (e) => e is svg.FETileElement, svg.FETileElement.supported); | 
|  | testConstructor('feTurbulence', (e) => e is svg.FETurbulenceElement, | 
|  | svg.FETurbulenceElement.supported); | 
|  | testConstructor( | 
|  | 'filter', (e) => e is svg.FilterElement, svg.FilterElement.supported); | 
|  | testConstructor('foreignObject', (e) => e is svg.ForeignObjectElement, | 
|  | svg.ForeignObjectElement.supported, false); | 
|  | testConstructor('metadata', (e) => e is svg.MetadataElement); | 
|  | testConstructor( | 
|  | 'set', (e) => e is svg.SetElement, svg.SetElement.supported); | 
|  | }); | 
|  |  | 
|  | group('outerHtml', () { | 
|  | test('outerHtml', () { | 
|  | final el = new svg.SvgSvgElement(); | 
|  | el.children.add(new svg.CircleElement()); | 
|  | el.children.add(new svg.PathElement()); | 
|  | expect( | 
|  | [ | 
|  | '<svg version="1.1"><circle></circle><path></path></svg>', | 
|  | '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">' | 
|  | '<circle /><path /></svg>', | 
|  | ].contains(el.outerHtml), | 
|  | true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('innerHtml', () { | 
|  | test('get', () { | 
|  | final el = new svg.SvgSvgElement(); | 
|  | el.children.add(new svg.CircleElement()); | 
|  | el.children.add(new svg.PathElement()); | 
|  | // Allow for odd IE serialization. | 
|  | expect( | 
|  | [ | 
|  | '<circle></circle><path></path>', | 
|  | '<circle xmlns="http://www.w3.org/2000/svg" />' | 
|  | '<path xmlns="http://www.w3.org/2000/svg" />' | 
|  | ].contains(el.innerHtml), | 
|  | true); | 
|  | }); | 
|  |  | 
|  | test('set', () { | 
|  | final el = new svg.SvgSvgElement(); | 
|  | el.children.add(new svg.CircleElement()); | 
|  | el.children.add(new svg.PathElement()); | 
|  | el.innerHtml = '<rect></rect><a></a>'; | 
|  | expect(_nodeStrings(el.children), ["rect", "a"]); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('elementget', () { | 
|  | test('get', () { | 
|  | final el = new svg.SvgElement.svg(""" | 
|  | <svg version="1.1"> | 
|  | <circle></circle> | 
|  | <path></path> | 
|  | text | 
|  | </svg>"""); | 
|  | expect(_nodeStrings(el.children), ["circle", "path"]); | 
|  | }); | 
|  |  | 
|  | test('resize', () { | 
|  | var el = new svg.SvgSvgElement(); | 
|  | var items = [new svg.CircleElement(), new svg.RectElement()]; | 
|  | el.children = items; | 
|  | expect(el.children.length, 2); | 
|  | el.children.length = 1; | 
|  | expect(el.children.length, 1); | 
|  | expect(el.children.contains(items[0]), true); | 
|  | expect(el.children.contains(items[1]), false); | 
|  |  | 
|  | el.children.length = 0; | 
|  | expect(el.children.contains(items[0]), false); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('elementset', () { | 
|  | test('set', () { | 
|  | final el = new svg.SvgSvgElement(); | 
|  | el.children = [ | 
|  | new svg.SvgElement.tag("circle"), | 
|  | new svg.SvgElement.tag("path") | 
|  | ]; | 
|  | expect(el.nodes.length, 2); | 
|  | expect(el.nodes[0] is svg.CircleElement, true); | 
|  | expect(el.nodes[1] is svg.PathElement, true); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('css', () { | 
|  | test('classes', () { | 
|  | var el = new svg.CircleElement(); | 
|  | var classes = el.classes; | 
|  | expect(el.classes.length, 0); | 
|  | classes.toggle('foo'); | 
|  | expect(el.classes.length, 1); | 
|  | classes.toggle('foo'); | 
|  | expect(el.classes.length, 0); | 
|  | }); | 
|  |  | 
|  | test('classes-add-bad', () { | 
|  | var el = new svg.CircleElement(); | 
|  | expect(() => el.classes.add(''), throws); | 
|  | expect(() => el.classes.add('foo bar'), throws); | 
|  | }); | 
|  | test('classes-remove-bad', () { | 
|  | var el = new svg.CircleElement(); | 
|  | expect(() => el.classes.remove(''), throws); | 
|  | expect(() => el.classes.remove('foo bar'), throws); | 
|  | }); | 
|  | test('classes-toggle-token', () { | 
|  | var el = new svg.CircleElement(); | 
|  | expect(() => el.classes.toggle(''), throws); | 
|  | expect(() => el.classes.toggle('', true), throws); | 
|  | expect(() => el.classes.toggle('', false), throws); | 
|  | expect(() => el.classes.toggle('foo bar'), throws); | 
|  | expect(() => el.classes.toggle('foo bar', true), throws); | 
|  | expect(() => el.classes.toggle('foo bar', false), throws); | 
|  | }); | 
|  | test('classes-contains-bad', () { | 
|  | var el = new svg.CircleElement(); | 
|  | // Non-strings => false, strings must be valid tokens. | 
|  | expect(el.classes.contains(1), isFalse); | 
|  | expect(() => el.classes.contains(''), throws); | 
|  | expect(() => el.classes.contains('foo bar'), throws); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('getBoundingClientRect', () { | 
|  | test('is a Rectangle', () { | 
|  | var element = new svg.RectElement(); | 
|  | element.attributes['width'] = '100'; | 
|  | element.attributes['height'] = '100'; | 
|  | var root = new svg.SvgSvgElement(); | 
|  | root.append(element); | 
|  |  | 
|  | document.body.append(root); | 
|  |  | 
|  | var rect = element.getBoundingClientRect(); | 
|  | expect(rect is Rectangle, isTrue); | 
|  | expect(rect.width, closeTo(100, 1)); | 
|  | expect(rect.height, closeTo(100, 1)); | 
|  | }); | 
|  | }); | 
|  | } |