| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, 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.web.js_interop_test; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:html'; | |
| 9 import 'dart:js'; | |
| 10 import 'package:polymer/polymer.dart'; | |
| 11 import 'package:unittest/html_config.dart'; | |
| 12 import 'package:unittest/unittest.dart'; | |
| 13 | |
| 14 @CustomTag('dart-element') | |
| 15 class DartElement extends PolymerElement { | |
| 16 DartElement.created() : super.created(); | |
| 17 } | |
| 18 | |
| 19 @CustomTag('dart-element2') | |
| 20 class DartElement2 extends PolymerElement { | |
| 21 Element get quux => this.querySelector('.quux'); | |
| 22 DartElement2.created() : super.created(); | |
| 23 } | |
| 24 | |
| 25 @CustomTag('dart-element3') | |
| 26 class DartElement3 extends PolymerElement { | |
| 27 @observable var quux; | |
| 28 DartElement3.created() : super.created(); | |
| 29 | |
| 30 domReady() { | |
| 31 quux = new JsObject.jsify({ | |
| 32 'aDartMethod': (x) => 444 + x | |
| 33 }); | |
| 34 } | |
| 35 } | |
| 36 | |
| 37 @CustomTag('dart-two-way') | |
| 38 class DartTwoWay extends PolymerElement { | |
| 39 @observable var twoWay = 40; | |
| 40 DartTwoWay.created() : super.created(); | |
| 41 } | |
| 42 | |
| 43 main() => initPolymer().run(() { | |
| 44 useHtmlConfiguration(); | |
| 45 | |
| 46 setUp(() => Polymer.onReady); | |
| 47 | |
| 48 test('dart-element upgraded', () { | |
| 49 expect(querySelector('dart-element') is DartElement, true, | |
| 50 reason: 'dart-element upgraded'); | |
| 51 }); | |
| 52 | |
| 53 test('js-element in body', () => testInterop( | |
| 54 querySelector('js-element'))); | |
| 55 | |
| 56 test('js-element in dart-element', () => testInterop( | |
| 57 querySelector('dart-element').shadowRoot.querySelector('js-element'))); | |
| 58 | |
| 59 test('elements can be passed through Node.bind to JS', () { | |
| 60 var text = querySelector('dart-element2') | |
| 61 .shadowRoot.querySelector('js-element2') | |
| 62 .shadowRoot.text; | |
| 63 expect(text, 'QUX:123'); | |
| 64 }); | |
| 65 | |
| 66 test('objects with functions can be passed through Node.bind to JS', () { | |
| 67 var sr = querySelector('dart-element3') | |
| 68 .shadowRoot.querySelector('js-element3') | |
| 69 .shadowRoot; | |
| 70 | |
| 71 return new Future(() { | |
| 72 expect(sr.text, 'js-element3[qux]:765'); | |
| 73 }); | |
| 74 }); | |
| 75 | |
| 76 test('two way bindings work', () { | |
| 77 var dartElem = querySelector('dart-two-way'); | |
| 78 var jsElem = dartElem.shadowRoot.querySelector('js-two-way'); | |
| 79 var interop = new JsObject.fromBrowserObject(jsElem); | |
| 80 | |
| 81 return new Future(() { | |
| 82 expect(jsElem.shadowRoot.text, 'FOOBAR:40'); | |
| 83 | |
| 84 expect(dartElem.twoWay, 40); | |
| 85 expect(interop['foobar'], 40); | |
| 86 | |
| 87 interop.callMethod('aJsMethod', [2]); | |
| 88 | |
| 89 // Because Polymer.js two-way bindings are just a getter/setter pair | |
| 90 // pointing at the original, we will see the new value immediately. | |
| 91 expect(dartElem.twoWay, 42); | |
| 92 | |
| 93 expect(interop['foobar'], 42); | |
| 94 | |
| 95 // Text will update asynchronously | |
| 96 expect(jsElem.shadowRoot.text, 'FOOBAR:40'); | |
| 97 | |
| 98 return _onTextChanged(jsElem.shadowRoot).then((_) { | |
| 99 expect(jsElem.shadowRoot.text, 'FOOBAR:42'); | |
| 100 }); | |
| 101 }); | |
| 102 }); | |
| 103 }); | |
| 104 | |
| 105 Future<List<MutationRecord>> _onTextChanged(Node node) { | |
| 106 var completer = new Completer(); | |
| 107 new MutationObserver((mutations, observer) { | |
| 108 observer.disconnect(); | |
| 109 completer.complete(mutations); | |
| 110 })..observe(node, characterData: true, subtree: true); | |
| 111 return completer.future; | |
| 112 } | |
| 113 | |
| 114 testInterop(jsElem) { | |
| 115 expect(jsElem.shadowRoot.text, 'FOOBAR'); | |
| 116 var interop = new JsObject.fromBrowserObject(jsElem); | |
| 117 expect(interop['baz'], 42, reason: 'can read JS custom element properties'); | |
| 118 | |
| 119 jsElem.attributes['baz'] = '123'; | |
| 120 return flush().then((_) { | |
| 121 expect(interop['baz'], 123, reason: 'attribute reflected to property'); | |
| 122 expect(jsElem.shadowRoot.text, 'FOOBAR', reason: 'text unchanged'); | |
| 123 | |
| 124 interop['baz'] = 777; | |
| 125 return flush(); | |
| 126 }).then((_) { | |
| 127 expect(jsElem.attributes['baz'], '777', | |
| 128 reason: 'property reflected to attribute'); | |
| 129 | |
| 130 expect(jsElem.shadowRoot.text, 'FOOBAR', reason: 'text unchanged'); | |
| 131 | |
| 132 interop.callMethod('aJsMethod', [123]); | |
| 133 return flush(); | |
| 134 }).then((_) { | |
| 135 expect(jsElem.shadowRoot.text, '900', reason: 'text set by JS method'); | |
| 136 expect(interop['baz'], 777, reason: 'unchanged'); | |
| 137 }); | |
| 138 } | |
| 139 | |
| 140 /// Calls Polymer.flush() to flush Polymer.js pending operations, e.g. | |
| 141 /// dirty checking for data-bindings. | |
| 142 Future flush() { | |
| 143 var Polymer = context['Polymer']; | |
| 144 Polymer.callMethod('flush'); | |
| 145 | |
| 146 var completer = new Completer(); | |
| 147 Polymer.callMethod('endOfMicrotask', [() => completer.complete()]); | |
| 148 return completer.future; | |
| 149 } | |
| OLD | NEW |