| Index: pkg/template_binding/test/custom_element_bindings_test.dart
|
| diff --git a/pkg/template_binding/test/custom_element_bindings_test.dart b/pkg/template_binding/test/custom_element_bindings_test.dart
|
| index cc128753d2d743fefa56b862ac0a9dd04b8cf6dd..d3c22c969850226b43064e9f9993206eb3e583af 100644
|
| --- a/pkg/template_binding/test/custom_element_bindings_test.dart
|
| +++ b/pkg/template_binding/test/custom_element_bindings_test.dart
|
| @@ -8,14 +8,14 @@ import 'dart:async';
|
| import 'dart:html';
|
| import 'package:custom_element/polyfill.dart';
|
| import 'package:template_binding/template_binding.dart';
|
| -import 'package:observe/observe.dart' show toObservable;
|
| +import 'package:observe/observe.dart';
|
| import 'package:unittest/html_config.dart';
|
| import 'package:unittest/unittest.dart';
|
| import 'utils.dart';
|
|
|
| Future _registered;
|
|
|
| -main() {
|
| +main() => dirtyCheckZone().run(() {
|
| useHtmlConfiguration();
|
|
|
| _registered = loadCustomElementPolyfill().then((_) {
|
| @@ -24,7 +24,7 @@ main() {
|
| });
|
|
|
| group('Custom Element Bindings', customElementBindingsTest);
|
| -}
|
| +});
|
|
|
| customElementBindingsTest() {
|
| setUp(() {
|
| @@ -37,13 +37,13 @@ customElementBindingsTest() {
|
| testDiv = null;
|
| });
|
|
|
| - observeTest('override bind/unbind/unbindAll', () {
|
| + test('override bind/unbind/unbindAll', () {
|
| var element = new MyCustomElement();
|
| var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
|
|
|
| nodeBind(element)
|
| - ..bind('my-point', model, 'a')
|
| - ..bind('scary-monster', model, 'b');
|
| + ..bind('my-point', new PathObserver(model, 'a'))
|
| + ..bind('scary-monster', new PathObserver(model, 'b'));
|
|
|
| expect(element.attributes, isNot(contains('my-point')));
|
| expect(element.attributes, isNot(contains('scary-monster')));
|
| @@ -52,65 +52,67 @@ customElementBindingsTest() {
|
| expect(element.scaryMonster, model['b']);
|
|
|
| model['a'] = null;
|
| - performMicrotaskCheckpoint();
|
| - expect(element.myPoint, null);
|
| - nodeBind(element).unbind('my-point');
|
| -
|
| - model['a'] = new Point(1, 2);
|
| - model['b'] = new Monster(200);
|
| - performMicrotaskCheckpoint();
|
| - expect(element.scaryMonster, model['b']);
|
| - expect(element.myPoint, null, reason: 'a was unbound');
|
| -
|
| - nodeBind(element).unbindAll();
|
| - model['b'] = null;
|
| - performMicrotaskCheckpoint();
|
| - expect(element.scaryMonster.health, 200);
|
| + return new Future(() {
|
| + expect(element.myPoint, null);
|
| + nodeBind(element).unbind('my-point');
|
| +
|
| + model['a'] = new Point(1, 2);
|
| + model['b'] = new Monster(200);
|
| + }).then(endOfMicrotask).then((_) {
|
| + expect(element.scaryMonster, model['b']);
|
| + expect(element.myPoint, null, reason: 'a was unbound');
|
| +
|
| + nodeBind(element).unbindAll();
|
| + model['b'] = null;
|
| + }).then(endOfMicrotask).then((_) {
|
| + expect(element.scaryMonster.health, 200);
|
| + });
|
| });
|
|
|
| - observeTest('override attribute setter', () {
|
| + test('override attribute setter', () {
|
| var element = new WithAttrsCustomElement();
|
| var model = toObservable({'a': 1, 'b': 2});
|
| - nodeBind(element).bind('hidden?', model, 'a');
|
| - nodeBind(element).bind('id', model, 'b');
|
| + nodeBind(element).bind('hidden?', new PathObserver(model, 'a'));
|
| + nodeBind(element).bind('id', new PathObserver(model, 'b'));
|
|
|
| expect(element.attributes, contains('hidden'));
|
| expect(element.attributes['hidden'], '');
|
| expect(element.id, '2');
|
|
|
| model['a'] = null;
|
| - performMicrotaskCheckpoint();
|
| - expect(element.attributes, isNot(contains('hidden')),
|
| - reason: 'null is false-y');
|
| -
|
| - model['a'] = false;
|
| - performMicrotaskCheckpoint();
|
| - expect(element.attributes, isNot(contains('hidden')));
|
| -
|
| - model['a'] = 'foo';
|
| - // TODO(jmesserly): this is here to force an ordering between the two
|
| - // changes. Otherwise the order depends on what order StreamController
|
| - // chooses to fire the two listeners in.
|
| - performMicrotaskCheckpoint();
|
| -
|
| - model['b'] = 'x';
|
| - performMicrotaskCheckpoint();
|
| - expect(element.attributes, contains('hidden'));
|
| - expect(element.attributes['hidden'], '');
|
| - expect(element.id, 'x');
|
| -
|
| - expect(element.attributes.log, [
|
| - ['remove', 'hidden?'],
|
| - ['[]=', 'hidden', ''],
|
| - ['[]=', 'id', '2'],
|
| - ['remove', 'hidden'],
|
| - ['remove', 'hidden'],
|
| - ['[]=', 'hidden', ''],
|
| - ['[]=', 'id', 'x'],
|
| - ]);
|
| + return new Future(() {
|
| + expect(element.attributes, isNot(contains('hidden')),
|
| + reason: 'null is false-y');
|
| +
|
| + model['a'] = false;
|
| + }).then(endOfMicrotask).then((_) {
|
| + expect(element.attributes, isNot(contains('hidden')));
|
| +
|
| + model['a'] = 'foo';
|
| + // TODO(jmesserly): this is here to force an ordering between the two
|
| + // changes. Otherwise the order depends on what order StreamController
|
| + // chooses to fire the two listeners in.
|
| + }).then(endOfMicrotask).then((_) {
|
| +
|
| + model['b'] = 'x';
|
| + }).then(endOfMicrotask).then((_) {
|
| + expect(element.attributes, contains('hidden'));
|
| + expect(element.attributes['hidden'], '');
|
| + expect(element.id, 'x');
|
| +
|
| + expect(element.attributes.log, [
|
| + ['remove', 'hidden?'],
|
| + ['[]=', 'hidden', ''],
|
| + ['[]=', 'id', '2'],
|
| + ['remove', 'hidden'],
|
| + ['remove', 'hidden'],
|
| + ['[]=', 'hidden', ''],
|
| + ['[]=', 'id', 'x'],
|
| + ]);
|
| + });
|
| });
|
|
|
| - observeTest('template bind uses overridden custom element bind', () {
|
| + test('template bind uses overridden custom element bind', () {
|
|
|
| var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
|
| var div = createTestHtml('<template bind>'
|
| @@ -119,34 +121,36 @@ customElementBindingsTest() {
|
| '</template>');
|
|
|
| templateBind(div.query('template')).model = model;
|
| - performMicrotaskCheckpoint();
|
| + var element;
|
| + return new Future(() {
|
| + print('!!! running future');
|
| + element = div.nodes[1];
|
|
|
| - var element = div.nodes[1];
|
| + expect(element is MyCustomElement, true,
|
| + reason: '$element should be a MyCustomElement');
|
|
|
| - expect(element is MyCustomElement, true,
|
| - reason: '$element should be a MyCustomElement');
|
| + expect(element.myPoint, model['a']);
|
| + expect(element.scaryMonster, model['b']);
|
|
|
| - expect(element.myPoint, model['a']);
|
| - expect(element.scaryMonster, model['b']);
|
| + expect(element.attributes, isNot(contains('my-point')));
|
| + expect(element.attributes, isNot(contains('scary-monster')));
|
|
|
| - expect(element.attributes, isNot(contains('my-point')));
|
| - expect(element.attributes, isNot(contains('scary-monster')));
|
| -
|
| - model['a'] = null;
|
| - performMicrotaskCheckpoint();
|
| - expect(element.myPoint, null);
|
| + model['a'] = null;
|
| + }).then(endOfMicrotask).then((_) {
|
| + expect(element.myPoint, null);
|
|
|
| - templateBind(div.query('template')).model = null;
|
| - performMicrotaskCheckpoint();
|
| + templateBind(div.query('template')).model = null;
|
| + }).then(endOfMicrotask).then((_) {
|
|
|
| - expect(element.parentNode, null, reason: 'element was detached');
|
| + expect(element.parentNode, null, reason: 'element was detached');
|
|
|
| - model['a'] = new Point(1, 2);
|
| - model['b'] = new Monster(200);
|
| - performMicrotaskCheckpoint();
|
| + model['a'] = new Point(1, 2);
|
| + model['b'] = new Monster(200);
|
| + }).then(endOfMicrotask).then((_) {
|
|
|
| - expect(element.myPoint, null, reason: 'model was unbound');
|
| - expect(element.scaryMonster.health, 100, reason: 'model was unbound');
|
| + expect(element.myPoint, null, reason: 'model was unbound');
|
| + expect(element.scaryMonster.health, 100, reason: 'model was unbound');
|
| + });
|
| });
|
|
|
| }
|
| @@ -165,35 +169,30 @@ class MyCustomElement extends HtmlElement implements NodeBindExtension {
|
|
|
| MyCustomElement.created() : super.created();
|
|
|
| - NodeBinding bind(String name, model, [String path]) {
|
| + Bindable bind(String name, value, {oneTime: false}) {
|
| switch (name) {
|
| case 'my-point':
|
| case 'scary-monster':
|
| attributes.remove(name);
|
| + if (oneTime) {
|
| + _setProperty(name, value);
|
| + return null;
|
| + }
|
| unbind(name);
|
| - return bindings[name] = new _MyCustomBinding(this, name, model, path);
|
| + _setProperty(name, value.open((x) => _setProperty(name, x)));
|
| + return bindings[name] = value;
|
| }
|
| - return nodeBindFallback(this).bind(name, model, path);
|
| + return nodeBindFallback(this).bind(name, value, oneTime: oneTime);
|
| }
|
|
|
| unbind(name) => nodeBindFallback(this).unbind(name);
|
| unbindAll() => nodeBindFallback(this).unbindAll();
|
| get bindings => nodeBindFallback(this).bindings;
|
| get templateInstance => nodeBindFallback(this).templateInstance;
|
| -}
|
| -
|
| -class _MyCustomBinding extends NodeBinding {
|
| - _MyCustomBinding(MyCustomElement node, property, model, path)
|
| - : super(node, property, model, path) {
|
| -
|
| - node.attributes.remove(property);
|
| - }
|
| -
|
| - MyCustomElement get node => super.node;
|
|
|
| - void valueChanged(newValue) {
|
| - if (property == 'my-point') node.myPoint = newValue;
|
| - if (property == 'scary-monster') node.scaryMonster = newValue;
|
| + void _setProperty(String property, newValue) {
|
| + if (property == 'my-point') myPoint = newValue;
|
| + if (property == 'scary-monster') scaryMonster = newValue;
|
| }
|
| }
|
|
|
|
|