Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Unified Diff: pkg/polymer_expressions/test/syntax_test.dart

Issue 141703024: Refactor of PolymerExpressions. Adds "as" expressions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Reviewable state. More readable tests. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/polymer_expressions/test/syntax_test.dart
diff --git a/pkg/polymer_expressions/test/syntax_test.dart b/pkg/polymer_expressions/test/syntax_test.dart
index b5dc01f3ad3788f01e6d7424d0f1e0b7627302eb..7e597027e015632cef489e2fdeab484cea2421a4 100644
--- a/pkg/polymer_expressions/test/syntax_test.dart
+++ b/pkg/polymer_expressions/test/syntax_test.dart
@@ -16,98 +16,224 @@ main() {
useHtmlEnhancedConfiguration();
group('PolymerExpressions', () {
- var testDiv;
+ DivElement testDiv;
setUp(() {
document.body.append(testDiv = new DivElement());
});
tearDown(() {
- testDiv.firstChild.remove();
+ testDiv.children.clear();
testDiv = null;
});
- test('should make two-way bindings to inputs', () {
- testDiv.nodes.add(new Element.html('''
- <template id="test" bind>
- <input id="input" value="{{ firstName }}">
- </template>'''));
- var person = new Person('John', 'Messerly', ['A', 'B', 'C']);
- templateBind(query('#test'))
- ..bindingDelegate = new PolymerExpressions()
- ..model = person;
- return new Future.delayed(new Duration()).then((_) {
- InputElement input = query('#input');
- expect(input.value, 'John');
- input.focus();
- input.value = 'Justin';
- input.blur();
- var event = new Event('change');
- // TODO(justin): figure out how to trigger keyboard events to test
- // two-way bindings
- });
+ Future<Element> setUpTest(String html, {model: null, Map globals: null}) {
Jennifer Messerly 2014/01/31 02:48:50 : null is not needed
justinfagnani 2014/03/12 23:21:30 Done.
+ testDiv.innerHtml = html;
+ templateBind(querySelector('#test'))
+ ..bindingDelegate = new PolymerExpressions(globals: globals)
+ ..model = model;
+ return waitForChange(testDiv);
+ }
+
+ group('with template bind', () {
+
+ test('should show a simple binding', () =>
+ setUpTest('''
+ <template id="test" bind>
+ <div>{{ data + 'b' }}</div>
+ </template>''',
+ model: new Model('a'))
+ .then((_) {
+ expect(testDiv.children.length, 2);
+ expect(testDiv.children[1].text, 'ab');
+ }));
+
+ test('should handle an expression in the bind attribute', () =>
+ setUpTest('''
+ <template id="test" bind="{{ data }}">
+ <div>{{ this }}</div>
+ </template>''',
+ model: new Model('a'))
+ .then((_) {
+ expect(testDiv.children.length, 2);
+ expect(testDiv.children[1].text, 'a');
+ }));
+
+ test('should handle an "as" expression in the bind attribute', () =>
+ setUpTest('''
+ <template id="test" bind="{{ data as a }}">
+ <div>{{ data }}</div>
+ <div>{{ a }}</div>
+ </template>''',
+ model: new Model('a'))
+ .then((_) {
+ expect(testDiv.children.length, 3);
+ expect(testDiv.children[1].text, 'a');
+ expect(testDiv.children[2].text, 'a');
+ }));
+
+ /**
+ * This test fails in dart2js because we appear to be tickling a bug in
+ * mirrors via _TemplateIterator.
+ */
+ skip_test('should resolve names in the outer template from within a nested '
+ 'template', () =>
+ setUpTest('''
+ <template id="test" bind>
+ <div>{{ a }}</div>
+ <div>{{ b }}</div>
+ <template bind="{{ b }}">
+ <div>{{ a }}</div>
+ <div>{{ b }}</div>
+ <div>{{ }}</div>
+ </template>
+ </template>''',
+ globals: {'a': 'aaa', 'b': 'bbb'})
+ .then((_) {
+ print("A");
+ expect(testDiv.children.map((c) => c.text),
+ ['', 'aaa', 'bbb', '', 'aaa', 'bbb', 'bbb']);
+ }));
+
+ test('should shadow names in the outer template from within a nested '
+ 'template', () =>
+ setUpTest('''
+ <template id="test" bind>
+ <div>{{ a }}</div>
+ <div>{{ b }}</div>
+ <template bind="{{ b as a}}">
+ <div>{{ a }}</div>
+ <div>{{ b }}</div>
+ </template>
+ </template>''',
+ globals: {'a': 'aaa', 'b': 'bbb'})
+ .then((_) {
+ expect(testDiv.children.map((c) => c.text),
+ ['', 'aaa', 'bbb', '', 'bbb', 'bbb']);
+ }));
+
});
- test('should handle null collections in "in" expressions', () {
- testDiv.nodes.add(new Element.html('''
- <template id="test" bind>
- <template repeat="{{ item in items }}">
- {{ item }}
- </template>
- </template>'''));
- templateBind(query('#test')).bindingDelegate =
- new PolymerExpressions(globals: {'items': null});
- // the template should be the only node
- expect(testDiv.nodes.length, 1);
- expect(testDiv.nodes[0].id, 'test');
+ group('with template repeat', () {
+
+ test('should handle "in" expressions', () =>
+ setUpTest('''
+ <template id="test" bind>
+ <div>{{ data }}</div>
+ <template repeat="{{ item in items }}">
+ <div>{{ item }}{{ data }}</div>
+ </template>
+ </template>''',
+ globals: {'items': [1, 2, 3]},
+ model: new Model('a'))
+ .then((_) {
+ // expect 6 children: two templates, a div and three instances
+ expect(testDiv.children.map((c) => c.text),
+ ['', 'a', '', '1a', '2a', '3a']);
+ }));
+
});
- test('should silently handle bad variable names', () {
- var logger = new Logger('polymer_expressions');
- var logFuture = logger.onRecord.toList();
- testDiv.nodes.add(new Element.html('''
- <template id="test" bind>{{ foo }}</template>'''));
- templateBind(query('#test')).bindingDelegate = new PolymerExpressions();
- return new Future(() {
- logger.clearListeners();
- return logFuture.then((records) {
- expect(records.length, 1);
- expect(records.first.message,
- contains('Error evaluating expression'));
- expect(records.first.message, contains('foo'));
+ group('with template if', () {
+
+ Future doTest(value, bool shouldRender) =>
+ setUpTest('''
+ <template id="test" bind>
+ <div>{{ data }}</div>
+ <template if="{{ show }}">
+ <div>{{ data }}</div>
+ </template>
+ </template>''',
+ globals: {'show': value},
+ model: new Model('a'))
+ .then((_) {
+ if (shouldRender) {
+ expect(testDiv.children.length, 4);
+ expect(testDiv.children[1].text, 'a');
+ expect(testDiv.children[3].text, 'a');
+ } else {
+ expect(testDiv.children.length, 3);
+ expect(testDiv.children[1].text, 'a');
+ }
});
- });
- });
- });
-}
-@reflectable
-class Person extends ChangeNotifier {
- String _firstName;
- String _lastName;
- List<String> _items;
+ test('should render for a true expression',
+ () => doTest(true, true));
- Person(this._firstName, this._lastName, this._items);
+ test('should treat a non-null expression as truthy',
+ () => doTest('a', true));
- String get firstName => _firstName;
+ test('should treat an empty list as truthy',
+ () => doTest([], true));
- void set firstName(String value) {
- _firstName = notifyPropertyChange(#firstName, _firstName, value);
- }
+ test('should handle a false expression',
+ () => doTest(false, false));
- String get lastName => _lastName;
+ test('should treat null as falsey',
+ () => doTest(null, false));
+ });
- void set lastName(String value) {
- _lastName = notifyPropertyChange(#lastName, _lastName, value);
- }
+ group('error handling', () {
+
+ test('should handle and log bad variable names', () {
+ var logger = new Logger('polymer_expressions');
+ var logFuture = logger.onRecord.toList();
+ return setUpTest('''
+ <template id="test" bind>
+ <span>A</span>
+ <span>{{ foo }}</span>
+ <span>B</span>
+ </template>''')
+ .then((_) {
+ expect(testDiv.children.length, 4);
+ expect(testDiv.children.skip(1).map((c) => c.text), ['A', '', 'B']);
+ logger.clearListeners();
+ return logFuture.then((records) {
+ expect(records.length, 1);
+ expect(records.first.message,
+ contains('Error evaluating expression'));
+ expect(records.first.message, contains('foo'));
+ });
+ });
+ });
+
+ test('should handle null collections in "in" expressions', () =>
+ setUpTest('''
+ <template id="test" bind>
+ <template repeat="{{ item in items }}">
+ {{ item }}
+ </template>
+ </template>''',
+ globals: {'items': null})
+ .then((_) {
+ expect(testDiv.children.length, 2);
+ expect(testDiv.children[0].id, 'test');
+ }));
+
+ });
+ });
+}
+
+Future<Element> waitForChange(Element e) {
+ var completer = new Completer<Element>();
+ new MutationObserver((mutations, observer) {
+ observer.disconnect();
+ completer.complete(e);
+ }).observe(e, childList: true);
+ return completer.future;
+}
+
+@reflectable
+class Model extends ChangeNotifier {
+ String _data;
- String getFullName() => '$_firstName $_lastName';
+ Model(this._data);
- List<String> get items => _items;
+ String get data => _data;
- void set items(List<String> value) {
- _items = notifyPropertyChange(#items, _items, value);
+ void set data(String value) {
+ _data = notifyPropertyChange(#data, _data, value);
}
- String toString() => "Person(firstName: $_firstName, lastName: $_lastName)";
+ String toString() => "Model(data: $_data)";
}

Powered by Google App Engine
This is Rietveld 408576698