Index: test/codegen/lib/html/element_test.dart |
diff --git a/test/codegen/lib/html/element_test.dart b/test/codegen/lib/html/element_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c1f74b586221fb298e32fe6f7d72c76b2cb8641d |
--- /dev/null |
+++ b/test/codegen/lib/html/element_test.dart |
@@ -0,0 +1,1000 @@ |
+// 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 ElementTest; |
+ |
+import 'package:unittest/unittest.dart'; |
+import 'package:unittest/html_individual_config.dart'; |
+import 'dart:async'; |
+import 'dart:html'; |
+import 'dart:svg' as svg; |
+import 'utils.dart'; |
+ |
+expectLargeRect(Rectangle rect) { |
+ expect(rect.top, 0); |
+ expect(rect.left, 0); |
+ expect(rect.width, greaterThan(100)); |
+ expect(rect.height, greaterThan(100)); |
+ expect(rect.bottom, rect.top + rect.height); |
+ expect(rect.right, rect.left + rect.width); |
+} |
+ |
+void testUnsupported(String name, void f()) { |
+ test(name, () { |
+ expect(f, throwsUnsupportedError); |
+ }); |
+} |
+ |
+main() { |
+ useHtmlIndividualConfiguration(); |
+ |
+ var isHRElement = predicate((x) => x is HRElement, 'is a HRElement'); |
+ var isBRElement = predicate((x) => x is BRElement, 'is a BRElement'); |
+ var isInputElement = |
+ predicate((x) => x is InputElement, 'is an InputElement'); |
+ var isImageElement = |
+ predicate((x) => x is ImageElement, 'is an ImageElement'); |
+ var isSpanElement = predicate((x) => x is SpanElement, 'is a SpanElement'); |
+ var isAnchorElement = |
+ predicate((x) => x is AnchorElement, 'is an AnchorElement'); |
+ var isElementList = |
+ predicate((x) => x is List<Element>, 'is a List<Element>'); |
+ var isElementIterable = |
+ predicate((x) => x is Iterable<Element>, 'is an Iterable<Element>'); |
+ var isHeadingElement = |
+ predicate((x) => x is HeadingElement, 'is a HeadingElement'); |
+ |
+ Element makeElement() => new Element.tag('div'); |
+ |
+ Element makeElementWithChildren() => |
+ new Element.html("<div><br/><img/><input/></div>"); |
+ |
+ group('position', () { |
+ test('computedStyle', () { |
+ final element = document.body; |
+ var style = element.getComputedStyle(); |
+ expect(style.getPropertyValue('left'), 'auto'); |
+ }); |
+ |
+ test('client position synchronous', () { |
+ final container = new Element.tag("div"); |
+ container.style.position = 'absolute'; |
+ container.style.top = '8px'; |
+ container.style.left = '9px'; |
+ final element = new Element.tag("div"); |
+ element.style.width = '200px'; |
+ element.style.height = '200px'; |
+ container.children.add(element); |
+ document.body.children.add(container); |
+ |
+ expect(element.client.width, greaterThan(100)); |
+ expect(element.client.height, greaterThan(100)); |
+ expect(element.offset.width, greaterThan(100)); |
+ expect(element.offset.height, greaterThan(100)); |
+ expect(element.scrollWidth, greaterThan(100)); |
+ expect(element.scrollHeight, greaterThan(100)); |
+ expect(element.getBoundingClientRect().left, 9); |
+ expect(element.getBoundingClientRect().top, 8); |
+ |
+ expect(element.documentOffset.x, 9); |
+ expect(element.documentOffset.y, 8); |
+ container.remove(); |
+ }); |
+ }); |
+ |
+ group('constructors', () { |
+ test('error', () { |
+ expect(() => new Element.html('<br/><br/>'), throwsStateError); |
+ }); |
+ |
+ test('.html has no parent', |
+ () => expect(new Element.html('<br/>').parent, isNull)); |
+ |
+ test('.html table', () { |
+ // http://developers.whatwg.org/tabular-data.html#tabular-data |
+ var node = new Element.html(''' |
+<table> |
+ <caption>Characteristics with positive and negative sides</caption> |
+ <thead> |
+ <tr> |
+ <th id="n"> Negative |
+ <th> Characteristic |
+ <th> Positive |
+ <tbody> |
+ <tr> |
+ <td headers="n r1"> Sad |
+ <th id="r1"> Mood |
+ <td> Happy |
+ <tr> |
+ <td headers="n r2"> Failing |
+ <th id="r2"> Grade |
+ <td> Passing |
+</table>'''); |
+ expect(node, predicate((x) => x is TableElement, 'is a TableElement')); |
+ expect(node.tagName, 'TABLE'); |
+ expect(node.parent, isNull); |
+ expect(node.caption.innerHtml, |
+ 'Characteristics with positive and negative sides'); |
+ expect(node.tHead.rows.length, 1); |
+ expect(node.tHead.rows[0].cells.length, 3); |
+ expect(node.tBodies.length, 1); |
+ expect(node.tBodies[0].rows.length, 2); |
+ expect(node.tBodies[0].rows[1].cells.map((c) => c.innerHtml), |
+ [' Failing\n ', ' Grade\n ', ' Passing\n']); |
+ }); |
+ |
+ test('.html caption', () { |
+ var table = new TableElement(); |
+ var node = table.createFragment('<caption><p>Table 1.').nodes.single; |
+ expect( |
+ node, |
+ predicate( |
+ (x) => x is TableCaptionElement, 'is a TableCaptionElement')); |
+ expect(node.tagName, 'CAPTION'); |
+ expect(node.parent, isNull); |
+ expect(node.innerHtml, '<p>Table 1.</p>'); |
+ }); |
+ |
+ test('.html colgroup', () { |
+ var table = new TableElement(); |
+ var node = |
+ table.createFragment('<colgroup> <col> <col> <col>').nodes.single; |
+ expect( |
+ node, predicate((x) => x is TableColElement, 'is a TableColElement')); |
+ expect(node.tagName, 'COLGROUP'); |
+ expect(node.parent, isNull); |
+ expect(node.innerHtml, ' <col> <col> <col>'); |
+ }); |
+ |
+ test('.html tbody', () { |
+ var innerHtml = '<tr><td headers="n r1">Sad</td><td>Happy</td></tr>'; |
+ var table = new TableElement(); |
+ var node = table.createFragment('<tbody>$innerHtml').nodes.single; |
+ expect( |
+ node, |
+ predicate( |
+ (x) => x is TableSectionElement, 'is a TableSectionElement')); |
+ expect(node.tagName, 'TBODY'); |
+ expect(node.parent, isNull); |
+ expect(node.rows.length, 1); |
+ expect(node.rows[0].cells.length, 2); |
+ expect(node.innerHtml, innerHtml); |
+ }); |
+ |
+ test('.html thead', () { |
+ var innerHtml = '<tr><th id="n">Negative</th><th>Positive</th></tr>'; |
+ var table = new TableElement(); |
+ var node = table.createFragment('<thead>$innerHtml').nodes.single; |
+ expect( |
+ node, |
+ predicate( |
+ (x) => x is TableSectionElement, 'is a TableSectionElement')); |
+ expect(node.tagName, 'THEAD'); |
+ expect(node.parent, isNull); |
+ expect(node.rows.length, 1); |
+ expect(node.rows[0].cells.length, 2); |
+ expect(node.innerHtml, innerHtml); |
+ }); |
+ |
+ test('.html tfoot', () { |
+ var innerHtml = '<tr><th>percentage</th><td>34.3%</td></tr>'; |
+ var table = new TableElement(); |
+ var node = table.createFragment('<tfoot>$innerHtml').nodes.single; |
+ expect( |
+ node, |
+ predicate( |
+ (x) => x is TableSectionElement, 'is a TableSectionElement')); |
+ expect(node.tagName, 'TFOOT'); |
+ expect(node.parent, isNull); |
+ expect(node.rows.length, 1); |
+ expect(node.rows[0].cells.length, 2); |
+ expect(node.innerHtml, innerHtml); |
+ }); |
+ |
+ test('.html tr', () { |
+ var table = new TableElement(); |
+ document.body.append(table); |
+ var tBody = table.createTBody(); |
+ var node = tBody.createFragment('<tr><td>foo<td>bar').nodes.single; |
+ expect( |
+ node, predicate((x) => x is TableRowElement, 'is a TableRowElement')); |
+ expect(node.tagName, 'TR'); |
+ expect(node.parent, isNull); |
+ expect(node.cells.map((c) => c.innerHtml), ['foo', 'bar']); |
+ }); |
+ |
+ test('.html td', () { |
+ var table = new TableElement(); |
+ document.body.append(table); |
+ var tBody = table.createTBody(); |
+ var tRow = tBody.addRow(); |
+ var node = tRow.createFragment('<td>foobar').nodes.single; |
+ expect(node, |
+ predicate((x) => x is TableCellElement, 'is a TableCellElement')); |
+ expect(node.tagName, 'TD'); |
+ expect(node.parent, isNull); |
+ expect(node.innerHtml, 'foobar'); |
+ }); |
+ |
+ test('.html th', () { |
+ var table = new TableElement(); |
+ document.body.append(table); |
+ var tBody = table.createTBody(); |
+ var tRow = tBody.addRow(); |
+ var node = tRow.createFragment('<th>foobar').nodes.single; |
+ expect(node, |
+ predicate((x) => x is TableCellElement, 'is a TableCellElement')); |
+ expect(node.tagName, 'TH'); |
+ expect(node.parent, isNull); |
+ expect(node.innerHtml, 'foobar'); |
+ }); |
+ |
+ test('.html can fire events', () { |
+ var e = new Element.html('<button>aha</button>'); |
+ var gotEvent = false; |
+ e.onClick.listen((_) { |
+ gotEvent = true; |
+ }); |
+ e.click(); |
+ expect(gotEvent, isTrue, reason: 'click should have raised click event'); |
+ }); |
+ }); |
+ |
+ group('eventListening', () { |
+ test('streams', () { |
+ final target = new TextAreaElement(); |
+ |
+ void testEvent(Stream stream, String type, [createEvent(String type)]) { |
+ var firedOnEvent = false; |
+ stream.listen((e) { |
+ firedOnEvent = true; |
+ }); |
+ expect(firedOnEvent, isFalse); |
+ var event = createEvent != null ? createEvent(type) : new Event(type); |
+ target.dispatchEvent(event); |
+ |
+ expect(firedOnEvent, isTrue); |
+ } |
+ |
+ testEvent(target.onAbort, 'abort'); |
+ testEvent(target.onBeforeCopy, 'beforecopy'); |
+ testEvent(target.onBeforeCut, 'beforecut'); |
+ testEvent(target.onBeforePaste, 'beforepaste'); |
+ testEvent(target.onBlur, 'blur'); |
+ testEvent(target.onChange, 'change'); |
+ testEvent( |
+ target.onContextMenu, 'contextmenu', (type) => new MouseEvent(type)); |
+ // We cannot test dispatching a true ClipboardEvent as the DOM does not |
+ // provide a way to create a fake ClipboardEvent. |
+ testEvent(target.onCopy, 'copy'); |
+ testEvent(target.onCut, 'cut'); |
+ testEvent(target.onPaste, 'paste'); |
+ |
+ testEvent( |
+ target.onDoubleClick, 'dblclick', (type) => new MouseEvent(type)); |
+ testEvent(target.onDrag, 'drag', (type) => new MouseEvent(type)); |
+ testEvent(target.onDragEnd, 'dragend', (type) => new MouseEvent(type)); |
+ testEvent( |
+ target.onDragEnter, 'dragenter', (type) => new MouseEvent(type)); |
+ testEvent( |
+ target.onDragLeave, 'dragleave', (type) => new MouseEvent(type)); |
+ testEvent(target.onDragOver, 'dragover', (type) => new MouseEvent(type)); |
+ testEvent( |
+ target.onDragStart, 'dragstart', (type) => new MouseEvent(type)); |
+ testEvent(target.onDrop, 'drop', (type) => new MouseEvent(type)); |
+ testEvent(target.onError, 'error'); |
+ testEvent(target.onFocus, 'focus'); |
+ testEvent(target.onFullscreenChange, 'webkitfullscreenchange'); |
+ testEvent(target.onInput, 'input'); |
+ testEvent(target.onInvalid, 'invalid'); |
+ testEvent(target.onKeyDown, 'keydown', (type) => new KeyboardEvent(type)); |
+ testEvent( |
+ target.onKeyPress, 'keypress', (type) => new KeyboardEvent(type)); |
+ testEvent(target.onKeyUp, 'keyup', (type) => new KeyboardEvent(type)); |
+ testEvent(target.onLoad, 'load'); |
+ testEvent( |
+ target.onMouseDown, 'mousedown', (type) => new MouseEvent(type)); |
+ testEvent( |
+ target.onMouseMove, 'mousemove', (type) => new MouseEvent(type)); |
+ testEvent(target.onMouseOut, 'mouseout', (type) => new MouseEvent(type)); |
+ testEvent( |
+ target.onMouseOver, 'mouseover', (type) => new MouseEvent(type)); |
+ testEvent(target.onMouseUp, 'mouseup', (type) => new MouseEvent(type)); |
+ testEvent(target.onReset, 'reset'); |
+ testEvent(target.onScroll, 'scroll'); |
+ testEvent(target.onSearch, 'search'); |
+ testEvent(target.onSelect, 'select'); |
+ testEvent(target.onSelectStart, 'selectstart'); |
+ testEvent(target.onSubmit, 'submit'); |
+ // We would prefer to create new touch events for this test via |
+ // new TouchEvent(null, null, null, type) |
+ // but that fails on desktop browsers as touch is not enabled. |
+ testEvent(target.onTouchCancel, 'touchcancel'); |
+ testEvent(target.onTouchEnd, 'touchend'); |
+ testEvent(target.onTouchLeave, 'touchleave'); |
+ testEvent(target.onTouchMove, 'touchmove'); |
+ testEvent(target.onTouchStart, 'touchstart'); |
+ }); |
+ }); |
+ |
+ group('click', () { |
+ test('clickEvent', () { |
+ var e = new DivElement(); |
+ var firedEvent = false; |
+ e.onClick.listen((event) { |
+ firedEvent = true; |
+ }); |
+ expect(firedEvent, false); |
+ e.click(); |
+ expect(firedEvent, true); |
+ |
+ var e2 = new DivElement(); |
+ var firedEvent2 = false; |
+ e2.onClick.matches('.foo').listen((event) { |
+ firedEvent2 = true; |
+ }); |
+ e2.click(); |
+ expect(firedEvent2, false); |
+ e2.classes.add('foo'); |
+ e2.click(); |
+ expect(firedEvent2, true); |
+ }); |
+ }); |
+ |
+ group('attributes', () { |
+ test('manipulation', () { |
+ final element = new Element.html( |
+ '''<div class="foo" style="overflow: hidden" data-foo="bar" |
+ data-foo2="bar2" dir="rtl"> |
+ </div>''', |
+ treeSanitizer: new NullTreeSanitizer()); |
+ final attributes = element.attributes; |
+ expect(attributes['class'], 'foo'); |
+ expect(attributes['style'], startsWith('overflow: hidden')); |
+ expect(attributes['data-foo'], 'bar'); |
+ expect(attributes['data-foo2'], 'bar2'); |
+ expect(attributes.length, 5); |
+ expect(element.dataset.length, 2); |
+ element.dataset['foo'] = 'baz'; |
+ expect(element.dataset['foo'], 'baz'); |
+ expect(attributes['data-foo'], 'baz'); |
+ attributes['data-foo2'] = 'baz2'; |
+ expect(attributes['data-foo2'], 'baz2'); |
+ expect(element.dataset['foo2'], 'baz2'); |
+ expect(attributes['dir'], 'rtl'); |
+ |
+ final dataset = element.dataset; |
+ dataset.remove('foo2'); |
+ expect(attributes.length, 4); |
+ expect(dataset.length, 1); |
+ attributes.remove('style'); |
+ expect(attributes.length, 3); |
+ dataset['foo3'] = 'baz3'; |
+ expect(dataset.length, 2); |
+ expect(attributes.length, 4); |
+ attributes['style'] = 'width: 300px;'; |
+ expect(attributes.length, 5); |
+ }); |
+ |
+ test('namespaces', () { |
+ var element = |
+ new svg.SvgElement.svg('''<svg xmlns="http://www.w3.org/2000/svg" |
+ xmlns:xlink="http://www.w3.org/1999/xlink"> |
+ <image xlink:href="foo" data-foo="bar"/> |
+ </svg>''').children[0]; |
+ |
+ var attributes = element.attributes; |
+ expect(attributes.length, 1); |
+ expect(attributes['data-foo'], 'bar'); |
+ |
+ var xlinkAttrs = |
+ element.getNamespacedAttributes('http://www.w3.org/1999/xlink'); |
+ expect(xlinkAttrs.length, 1); |
+ expect(xlinkAttrs['href'], 'foo'); |
+ |
+ xlinkAttrs.remove('href'); |
+ expect(xlinkAttrs.length, 0); |
+ |
+ xlinkAttrs['href'] = 'bar'; |
+ expect(xlinkAttrs['href'], 'bar'); |
+ |
+ var randomAttrs = element.getNamespacedAttributes('http://example.com'); |
+ expect(randomAttrs.length, 0); |
+ randomAttrs['href'] = 'bar'; |
+ expect(randomAttrs.length, 1); |
+ }); |
+ }); |
+ |
+ group('children', () { |
+ test('is a subset of nodes', () { |
+ var el = new Element.html("<div>Foo<br/><img/></div>"); |
+ expect(el.nodes.length, 3); |
+ expect(el.children.length, 2); |
+ expect(el.nodes[1], el.children[0]); |
+ expect(el.nodes[2], el.children[1]); |
+ }); |
+ |
+ test('changes when an element is added to nodes', () { |
+ var el = new Element.html("<div>Foo<br/><img/></div>"); |
+ el.nodes.add(new Element.tag('hr')); |
+ expect(el.children.length, 3); |
+ expect(el.children[2], isHRElement); |
+ expect(el.nodes[3], el.children[2]); |
+ }); |
+ |
+ test('changes nodes when an element is added', () { |
+ var el = new Element.html("<div>Foo<br/><img/></div>"); |
+ el.children.add(new Element.tag('hr')); |
+ expect(el.nodes.length, 4); |
+ expect(el.nodes[3], isHRElement); |
+ expect(el.children[2], el.nodes[3]); |
+ }); |
+ |
+ test('last', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.last, isInputElement); |
+ }); |
+ |
+ test('forEach', () { |
+ var els = []; |
+ var el = makeElementWithChildren(); |
+ el.children.forEach((n) => els.add(n)); |
+ expect(els[0], isBRElement); |
+ expect(els[1], isImageElement); |
+ expect(els[2], isInputElement); |
+ }); |
+ |
+ test('where', () { |
+ var filtered = |
+ makeElementWithChildren().children.where((n) => n is ImageElement); |
+ expect(1, filtered.length); |
+ expect(filtered.first, isImageElement); |
+ expect(filtered, isElementIterable); |
+ }); |
+ |
+ test('every', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.every((n) => n is Element), isTrue); |
+ expect(el.children.every((n) => n is InputElement), isFalse); |
+ }); |
+ |
+ test('any', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.any((n) => n is InputElement), isTrue); |
+ expect(el.children.any((n) => n is svg.SvgElement), isFalse); |
+ }); |
+ |
+ test('isEmpty', () { |
+ expect(makeElement().children.isEmpty, isTrue); |
+ expect(makeElementWithChildren().children.isEmpty, isFalse); |
+ }); |
+ |
+ test('length', () { |
+ expect(makeElement().children.length, 0); |
+ expect(makeElementWithChildren().children.length, 3); |
+ }); |
+ |
+ test('[]', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children[0], isBRElement); |
+ expect(el.children[1], isImageElement); |
+ expect(el.children[2], isInputElement); |
+ }); |
+ |
+ test('[]=', () { |
+ var el = makeElementWithChildren(); |
+ el.children[1] = new Element.tag('hr'); |
+ expect(el.children[0], isBRElement); |
+ expect(el.children[1], isHRElement); |
+ expect(el.children[2], isInputElement); |
+ }); |
+ |
+ test('add', () { |
+ var el = makeElement(); |
+ el.children.add(new Element.tag('hr')); |
+ expect(el.children.last, isHRElement); |
+ }); |
+ |
+ test('iterator', () { |
+ var els = []; |
+ var el = makeElementWithChildren(); |
+ for (var subel in el.children) { |
+ els.add(subel); |
+ } |
+ expect(els[0], isBRElement); |
+ expect(els[1], isImageElement); |
+ expect(els[2], isInputElement); |
+ }); |
+ |
+ test('addAll', () { |
+ var el = makeElementWithChildren(); |
+ el.children.addAll([ |
+ new Element.tag('span'), |
+ new Element.tag('a'), |
+ new Element.tag('h1') |
+ ]); |
+ expect(el.children[0], isBRElement); |
+ expect(el.children[1], isImageElement); |
+ expect(el.children[2], isInputElement); |
+ expect(el.children[3], isSpanElement); |
+ expect(el.children[4], isAnchorElement); |
+ expect(el.children[5], isHeadingElement); |
+ }); |
+ |
+ test('insert', () { |
+ var element = new DivElement(); |
+ element.children.insert(0, new BRElement()); |
+ expect(element.children[0], isBRElement); |
+ element.children.insert(0, new HRElement()); |
+ expect(element.children[0], isHRElement); |
+ element.children.insert(1, new ImageElement()); |
+ expect(element.children[1], isImageElement); |
+ element.children.insert(element.children.length, new InputElement()); |
+ expect(element.children.last, isInputElement); |
+ }); |
+ |
+ test('clear', () { |
+ var el = makeElementWithChildren(); |
+ el.children.clear(); |
+ expect(el.children, equals([])); |
+ }); |
+ |
+ test('removeLast', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.removeLast(), isInputElement); |
+ expect(el.children.length, 2); |
+ expect(el.children.removeLast(), isImageElement); |
+ expect(el.children.length, 1); |
+ }); |
+ |
+ test('sublist', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.sublist(1, 2), isElementList); |
+ }); |
+ |
+ test('getRange', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.getRange(1, 2).length, 1); |
+ }); |
+ |
+ test('retainWhere', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.retainWhere((e) => true); |
+ expect(el.children.length, 3); |
+ |
+ el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.retainWhere((e) => false); |
+ expect(el.children.length, 0); |
+ |
+ el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.retainWhere((e) => e.localName == 'input'); |
+ expect(el.children.length, 1); |
+ |
+ el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.retainWhere((e) => e.localName == 'br'); |
+ expect(el.children.length, 1); |
+ }); |
+ |
+ test('removeWhere', () { |
+ var el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.removeWhere((e) => true); |
+ expect(el.children.length, 0); |
+ |
+ el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.removeWhere((e) => false); |
+ expect(el.children.length, 3); |
+ |
+ el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.removeWhere((e) => e.localName == 'input'); |
+ expect(el.children.length, 2); |
+ |
+ el = makeElementWithChildren(); |
+ expect(el.children.length, 3); |
+ el.children.removeWhere((e) => e.localName == 'br'); |
+ expect(el.children.length, 2); |
+ }); |
+ |
+ testUnsupported('sort', () { |
+ var l = makeElementWithChildren().children; |
+ l.sort(); |
+ }); |
+ |
+ testUnsupported('setRange', () { |
+ var l = makeElementWithChildren().children; |
+ l.setRange(0, 0, []); |
+ }); |
+ |
+ testUnsupported('replaceRange', () { |
+ var l = makeElementWithChildren().children; |
+ l.replaceRange(0, 0, []); |
+ }); |
+ |
+ testUnsupported('removeRange', () { |
+ var l = makeElementWithChildren().children; |
+ l.removeRange(0, 1); |
+ }); |
+ |
+ testUnsupported('insertAll', () { |
+ var l = makeElementWithChildren().children; |
+ l.insertAll(0, []); |
+ }); |
+ }); |
+ |
+ group('matches', () { |
+ test('matches', () { |
+ var element = new DivElement(); |
+ document.body.append(element); |
+ element.classes.add('test'); |
+ |
+ expect(element.matches('div'), true); |
+ expect(element.matches('span'), false); |
+ expect(element.matches('.test'), true); |
+ }); |
+ }); |
+ |
+ group('queryAll', () { |
+ List<Element> getQueryAll() { |
+ return new Element.html(""" |
+<div> |
+ <hr/> |
+ <a class='q' href='http://dartlang.org'>Dart!</a> |
+ <p> |
+ <span class='q'>Hello</span>, |
+ <em>world</em>! |
+ </p> |
+ <hr class='q'/> |
+</div> |
+""").queryAll('.q'); |
+ } |
+ |
+ List<Element> getEmptyQueryAll() => new Element.tag('div').queryAll('img'); |
+ |
+ test('last', () { |
+ expect(getQueryAll().last, isHRElement); |
+ }); |
+ |
+ test('forEach', () { |
+ var els = []; |
+ getQueryAll().forEach((el) => els.add(el)); |
+ expect(els[0], isAnchorElement); |
+ expect(els[1], isSpanElement); |
+ expect(els[2], isHRElement); |
+ }); |
+ |
+ test('map', () { |
+ var texts = getQueryAll().map((el) => el.text).toList(); |
+ expect(texts, equals(['Dart!', 'Hello', ''])); |
+ }); |
+ |
+ test('where', () { |
+ var filtered = getQueryAll().where((n) => n is SpanElement).toList(); |
+ expect(filtered.length, 1); |
+ expect(filtered[0], isSpanElement); |
+ expect(filtered, isElementList); |
+ }); |
+ |
+ test('every', () { |
+ var el = getQueryAll(); |
+ expect(el.every((n) => n is Element), isTrue); |
+ expect(el.every((n) => n is SpanElement), isFalse); |
+ }); |
+ |
+ test('any', () { |
+ var el = getQueryAll(); |
+ expect(el.any((n) => n is SpanElement), isTrue); |
+ expect(el.any((n) => n is svg.SvgElement), isFalse); |
+ }); |
+ |
+ test('isEmpty', () { |
+ expect(getEmptyQueryAll().isEmpty, isTrue); |
+ expect(getQueryAll().isEmpty, isFalse); |
+ }); |
+ |
+ test('length', () { |
+ expect(getEmptyQueryAll().length, 0); |
+ expect(getQueryAll().length, 3); |
+ }); |
+ |
+ test('[]', () { |
+ var els = getQueryAll(); |
+ expect(els[0], isAnchorElement); |
+ expect(els[1], isSpanElement); |
+ expect(els[2], isHRElement); |
+ }); |
+ |
+ test('iterator', () { |
+ var els = []; |
+ for (var subel in getQueryAll()) { |
+ els.add(subel); |
+ } |
+ expect(els[0], isAnchorElement); |
+ expect(els[1], isSpanElement); |
+ expect(els[2], isHRElement); |
+ }); |
+ |
+ test('sublist', () { |
+ expect(getQueryAll().sublist(1, 2) is List<Element>, isTrue); |
+ }); |
+ |
+ testUnsupported('[]=', () => getQueryAll()[1] = new Element.tag('br')); |
+ testUnsupported('add', () => getQueryAll().add(new Element.tag('br'))); |
+ |
+ testUnsupported('addAll', () { |
+ getQueryAll().addAll([ |
+ new Element.tag('span'), |
+ new Element.tag('a'), |
+ new Element.tag('h1') |
+ ]); |
+ }); |
+ |
+ testUnsupported('sort', () => getQueryAll().sort((a1, a2) => true)); |
+ |
+ testUnsupported('setRange', () { |
+ getQueryAll().setRange(0, 1, [new BRElement()]); |
+ }); |
+ |
+ testUnsupported('removeRange', () => getQueryAll().removeRange(0, 1)); |
+ |
+ testUnsupported('clear', () => getQueryAll().clear()); |
+ |
+ testUnsupported('removeLast', () => getQueryAll().removeLast()); |
+ }); |
+ |
+ group('functional', () { |
+ test('toString', () { |
+ final elems = makeElementWithChildren().children; |
+ expect(elems.toString(), "[br, img, input]"); |
+ final elem = makeElement().children; |
+ expect(elem.toString(), '[]'); |
+ }); |
+ |
+ test('scrollIntoView', () { |
+ var child = new DivElement(); |
+ document.body.append(child); |
+ |
+ child.scrollIntoView(ScrollAlignment.TOP); |
+ child.scrollIntoView(ScrollAlignment.BOTTOM); |
+ child.scrollIntoView(ScrollAlignment.CENTER); |
+ child.scrollIntoView(); |
+ }); |
+ }); |
+ |
+ group('_ElementList', () { |
+ List<Element> makeElList() => makeElementWithChildren().children; |
+ |
+ test('where', () { |
+ var filtered = makeElList().where((n) => n is ImageElement); |
+ expect(filtered.length, 1); |
+ expect(filtered.first, isImageElement); |
+ expect(filtered, isElementIterable); |
+ }); |
+ |
+ test('sublist', () { |
+ var range = makeElList().sublist(1, 3); |
+ expect(range, isElementList); |
+ expect(range[0], isImageElement); |
+ expect(range[1], isInputElement); |
+ }); |
+ }); |
+ |
+ group('eventDelegation', () { |
+ test('matches', () { |
+ Element clickOne = new Element.a(); |
+ Element selectorOne = new Element.div() |
+ ..classes.add('selector') |
+ ..children.add(clickOne); |
+ |
+ Element clickTwo = new Element.a(); |
+ Element selectorTwo = new Element.div() |
+ ..classes.add('selector') |
+ ..children.add(clickTwo); |
+ document.body.append(selectorOne); |
+ document.body.append(selectorTwo); |
+ |
+ document.body.onClick |
+ .matches('.selector') |
+ .listen(expectAsync((Event event) { |
+ expect(event.currentTarget, document.body); |
+ expect(event.target, clickOne); |
+ expect(event.matchingTarget, selectorOne); |
+ })); |
+ |
+ selectorOne.onClick |
+ .matches('.selector') |
+ .listen(expectAsync((Event event) { |
+ expect(event.currentTarget, selectorOne); |
+ expect(event.target, clickOne); |
+ expect(event.matchingTarget, selectorOne); |
+ })); |
+ clickOne.click(); |
+ |
+ Element elem = new Element.div()..classes.addAll(['a', 'b']); |
+ Element img = new Element.img() |
+ ..classes.addAll(['b', 'a', 'd']) |
+ ..id = 'cookie'; |
+ Element input = new InputElement()..classes.addAll(['c', 'd']); |
+ var div = new Element.div() |
+ ..classes.add('a') |
+ ..id = 'wat'; |
+ document.body.append(elem); |
+ document.body.append(img); |
+ document.body.append(input); |
+ document.body.append(div); |
+ |
+ Element elem4 = new Element.div()..classes.addAll(['i', 'j']); |
+ Element elem5 = new Element.div() |
+ ..classes.addAll(['g', 'h']) |
+ ..children.add(elem4); |
+ Element elem6 = new Element.div() |
+ ..classes.addAll(['e', 'f']) |
+ ..children.add(elem5); |
+ document.body.append(elem6); |
+ |
+ var firedEvent = false; |
+ var elems = queryAll('.a'); |
+ queryAll('.a').onClick.listen((event) { |
+ firedEvent = true; |
+ }); |
+ expect(firedEvent, false); |
+ query('.c').click(); |
+ expect(firedEvent, false); |
+ query('#wat').click(); |
+ expect(firedEvent, true); |
+ |
+ var firedEvent4 = false; |
+ queryAll('.a').onClick.matches('.d').listen((event) { |
+ firedEvent4 = true; |
+ }); |
+ expect(firedEvent4, false); |
+ query('.c').click(); |
+ expect(firedEvent4, false); |
+ query('#wat').click(); |
+ expect(firedEvent4, false); |
+ query('#cookie').click(); |
+ expect(firedEvent4, true); |
+ |
+ var firedEvent2 = false; |
+ queryAll('.a').onClick.listen((event) { |
+ firedEvent2 = true; |
+ }); |
+ Element elem2 = new Element.html('<div class="a"><br/>'); |
+ document.body.append(elem2); |
+ elem2.click(); |
+ expect(firedEvent2, false); |
+ elem2.classes.add('a'); |
+ elem2.click(); |
+ expect(firedEvent2, false); |
+ |
+ var firedEvent3 = false; |
+ queryAll(':root').onClick.matches('.a').listen((event) { |
+ firedEvent3 = true; |
+ }); |
+ Element elem3 = new Element.html('<div class="d"><br/>'); |
+ document.body.append(elem3); |
+ elem3.click(); |
+ expect(firedEvent3, false); |
+ elem3.classes.add('a'); |
+ elem3.click(); |
+ expect(firedEvent3, true); |
+ |
+ var firedEvent5 = false; |
+ queryAll(':root').onClick.matches('.e').listen((event) { |
+ firedEvent5 = true; |
+ }); |
+ expect(firedEvent5, false); |
+ query('.i').click(); |
+ expect(firedEvent5, true); |
+ }); |
+ |
+ test('event ordering', () { |
+ var a = new DivElement(); |
+ var b = new DivElement(); |
+ a.append(b); |
+ var c = new DivElement(); |
+ b.append(c); |
+ |
+ var eventOrder = []; |
+ |
+ a.on['custom_event'].listen((_) { |
+ eventOrder.add('a no-capture'); |
+ }); |
+ |
+ a.on['custom_event'].capture((_) { |
+ eventOrder.add('a capture'); |
+ }); |
+ |
+ b.on['custom_event'].listen((_) { |
+ eventOrder.add('b no-capture'); |
+ }); |
+ |
+ b.on['custom_event'].capture((_) { |
+ eventOrder.add('b capture'); |
+ }); |
+ |
+ document.body.append(a); |
+ |
+ var event = new Event('custom_event', canBubble: true); |
+ c.dispatchEvent(event); |
+ expect(eventOrder, |
+ ['a capture', 'b capture', 'b no-capture', 'a no-capture']); |
+ }); |
+ }); |
+ |
+ group('ElementList', () { |
+ // Tests for methods on the DOM class 'NodeList'. |
+ // |
+ // There are two interesting things that are checked here from the viewpoint |
+ // of the dart2js implementation of a 'native' class: |
+ // |
+ // 1. Some methods are implementated from by 'Object' or 'Interceptor'; |
+ // some of these tests simply check that a method can be called. |
+ // 2. Some methods are implemented by mixins. |
+ |
+ ElementList<Element> makeElementList() => |
+ (new Element.html("<div>Foo<br/><!--baz--><br/><br/></div>")) |
+ .queryAll('br'); |
+ |
+ test('hashCode', () { |
+ var nodes = makeElementList(); |
+ var hash = nodes.hashCode; |
+ final int N = 1000; |
+ int matchCount = 0; |
+ for (int i = 0; i < N; i++) { |
+ if (makeElementList().hashCode == hash) matchCount++; |
+ } |
+ expect(matchCount, lessThan(N)); |
+ }); |
+ |
+ test('operator==', () { |
+ var a = [makeElementList(), makeElementList(), null]; |
+ for (int i = 0; i < a.length; i++) { |
+ for (int j = 0; j < a.length; j++) { |
+ expect(i == j, a[i] == a[j]); |
+ } |
+ } |
+ }); |
+ |
+ test('runtimeType', () { |
+ var nodes1 = makeElementList(); |
+ var nodes2 = makeElementList(); |
+ var type1 = nodes1.runtimeType; |
+ var type2 = nodes2.runtimeType; |
+ expect(type1 == type2, true); |
+ String name = '$type1'; |
+ if (name.length > 3) { |
+ expect(name.contains('ElementList'), true); |
+ } |
+ }); |
+ |
+ test('first', () { |
+ var nodes = makeElementList(); |
+ expect(nodes.first, isBRElement); |
+ }); |
+ |
+ test('last', () { |
+ var nodes = makeElementList(); |
+ expect(nodes.last, isBRElement); |
+ }); |
+ |
+ test('where', () { |
+ var filtered = makeElementList().where((n) => n is BRElement).toList(); |
+ expect(filtered.length, 3); |
+ expect(filtered[0], isBRElement); |
+ }); |
+ |
+ test('sublist', () { |
+ var range = makeElementList().sublist(1, 3); |
+ expect(range.length, 2); |
+ expect(range[0], isBRElement); |
+ expect(range[1], isBRElement); |
+ }); |
+ }); |
+} |