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 import 'dart:async'; | |
6 import 'dart:html'; | |
7 import 'package:unittest/unittest.dart'; | |
8 import 'package:unittest/html_config.dart'; | |
9 import 'package:polymer/polymer.dart'; | |
10 | |
11 class XAttrPublish extends PolymerElement { | |
12 XAttrPublish.created() : super.created(); | |
13 | |
14 @PublishedProperty(reflect: false) | |
15 String nog = ''; | |
16 } | |
17 | |
18 class XFoo extends PolymerElement { | |
19 XFoo.created() : super.created(); | |
20 | |
21 @PublishedProperty(reflect: true) var foo = ''; | |
22 @PublishedProperty(reflect: true) String baz = ''; | |
23 | |
24 @PublishedProperty(reflect: true) var def1, def2; | |
25 } | |
26 | |
27 class XBar extends XFoo { | |
28 XBar.created() : super.created(); | |
29 | |
30 @PublishedProperty(reflect: true) int zot = 3; | |
31 @PublishedProperty(reflect: true) bool zim = false; | |
32 @PublishedProperty(reflect: true) String str = 'str'; | |
33 @PublishedProperty(reflect: true) Object obj; | |
34 } | |
35 | |
36 class XZot extends XBar { | |
37 // Dart note: trying to make this roughly equivalent to the JS | |
38 @PublishedProperty(reflect: false) int get zot => super.zot; | |
39 @PublishedProperty(reflect: false) set zot(int x) { | |
40 super.zot = x; | |
41 } | |
42 | |
43 XZot.created() : super.created() { | |
44 zot = 2; | |
45 str = 'str2'; | |
46 } | |
47 } | |
48 | |
49 class XCompose extends PolymerElement { | |
50 XCompose.created() : super.created(); | |
51 | |
52 @observable bool zim = false; | |
53 } | |
54 | |
55 Future onAttributeChange(Element node) { | |
56 var completer = new Completer(); | |
57 new MutationObserver((records, observer) { | |
58 observer.disconnect(); | |
59 completer.complete(); | |
60 })..observe(node, attributes: true); | |
61 scheduleMicrotask(Observable.dirtyCheck); | |
62 return completer.future; | |
63 } | |
64 | |
65 main() => initPolymer().then((zone) => zone.run(() { | |
66 useHtmlConfiguration(); | |
67 | |
68 // Most tests use @CustomTag, here we test out the impertive register: | |
69 Polymer.register('x-foo', XFoo); | |
70 Polymer.register('x-bar', XBar); | |
71 Polymer.register('x-zot', XZot); | |
72 Polymer.register('x-compose', XCompose); | |
73 Polymer.register('x-attr-publish', XAttrPublish); | |
74 | |
75 setUp(() => Polymer.onReady); | |
76 | |
77 test('property to attribute reflection', () { | |
78 var xbasic = querySelector('x-basic'); | |
79 expect(xbasic.getAttribute('nog'), null, | |
80 reason: 'property published with `attributes` has correct initial ' | |
81 'value'); | |
82 xbasic.setAttribute('nog', 'hi'); | |
83 expect(xbasic.getAttribute('nog'), 'hi', | |
84 reason: 'deserialization of property published via `attributes`'); | |
85 | |
86 var xattrpublish = querySelector('x-attr-publish'); | |
87 expect(xattrpublish.nog, '', | |
88 reason: 'property published with `attributes` has correct initial ' | |
89 'value'); | |
90 xattrpublish.setAttribute('nog', 'hi'); | |
91 expect(xattrpublish.nog, 'hi', | |
92 reason: 'deserialization of property published via `attributes`'); | |
93 | |
94 var xcompose = querySelector('x-compose'); | |
95 var xfoo = querySelector('x-foo'); | |
96 expect(xfoo.foo, '', | |
97 reason: 'property published with info object has correct initial ' | |
98 'value'); | |
99 var xbar = querySelector('x-bar'); | |
100 expect(xbar.zim, false, | |
101 reason: 'property published with info object has correct initial ' | |
102 'value'); | |
103 expect(xbar.foo, '', | |
104 reason: 'property published with info object has correct initial ' | |
105 'value'); | |
106 var xzot = querySelector('x-zot'); | |
107 xfoo.foo = 5; | |
108 xfoo.attributes['def1'] = '15'; | |
109 xfoo.def2 = 15; | |
110 | |
111 // Dart note: our test here is more async than JS until we change | |
112 // Polymer.dart bindings to work like observe.js "bindToInstance". | |
113 return onAttributeChange(xfoo).then((_) { | |
114 expect(xcompose.$['bar'].attributes.containsKey('zim'), false, | |
115 reason: 'attribute bound to property updates when binding is made'); | |
116 | |
117 expect(xfoo.attributes['def2'], '15', | |
118 reason: 'default valued published property reflects to attr'); | |
119 | |
120 expect(xfoo.def1, 15, | |
121 reason: 'attr updates default valued published property'); | |
122 | |
123 expect('${xfoo.foo}', xfoo.attributes['foo'], | |
124 reason: 'attribute reflects property as string'); | |
125 xfoo.attributes['foo'] = '27'; | |
126 // TODO(jmesserly): why is JS leaving this as a String? From the code it | |
127 // looks like it should use the type of 5 and parse it as a number. | |
128 expect('${xfoo.foo}', xfoo.attributes['foo'], | |
129 reason: 'property reflects attribute'); | |
130 // | |
131 xfoo.baz = 'Hello'; | |
132 }).then((_) => onAttributeChange(xfoo)).then((_) { | |
133 expect(xfoo.baz, xfoo.attributes['baz'], | |
134 reason: 'attribute reflects property'); | |
135 // | |
136 xbar.foo = 'foo!'; | |
137 xbar.zot = 27; | |
138 xbar.zim = true; | |
139 xbar.str = 'str!'; | |
140 xbar.obj = {'hello': 'world'}; | |
141 }).then((_) => onAttributeChange(xbar)).then((_) { | |
142 expect(xbar.foo, xbar.attributes['foo'], | |
143 reason: 'inherited published property is reflected'); | |
144 expect('${xbar.zot}', xbar.attributes['zot'], | |
145 reason: 'attribute reflects property as number'); | |
146 expect(xbar.attributes['zim'], '', | |
147 reason: 'attribute reflects true valued boolean property as ' | |
148 'having attribute'); | |
149 expect(xbar.str, xbar.attributes['str'], | |
150 reason: 'attribute reflects property as published string'); | |
151 expect(xbar.attributes.containsKey('obj'), false, | |
152 reason: 'attribute does not reflect object property'); | |
153 xbar.attributes['zim'] = 'false'; | |
154 xbar.attributes['foo'] = 'foo!!'; | |
155 xbar.attributes['zot'] = '54'; | |
156 xbar.attributes['str'] = 'str!!'; | |
157 xbar.attributes['obj'] = "{'hello': 'world'}"; | |
158 expect(xbar.foo, xbar.attributes['foo'], | |
159 reason: 'property reflects attribute as string'); | |
160 expect(xbar.zot, 54, reason: 'property reflects attribute as number'); | |
161 expect(xbar.zim, false, reason: 'property reflects attribute as boolean'); | |
162 expect(xbar.str, 'str!!', | |
163 reason: 'property reflects attribute as published string'); | |
164 expect(xbar.obj, {'hello': 'world'}, | |
165 reason: 'property reflects attribute as object'); | |
166 xbar.zim = false; | |
167 }).then((_) => onAttributeChange(xbar)).then((_) { | |
168 expect(xbar.attributes.containsKey('zim'), false, | |
169 reason: 'attribute reflects false valued boolean property as NOT ' | |
170 'having attribute'); | |
171 xbar.obj = 'hi'; | |
172 }).then((_) => onAttributeChange(xbar)).then((_) { | |
173 expect(xbar.attributes['obj'], 'hi', | |
174 reason: 'reflect property based on current type'); | |
175 | |
176 expect(xzot.str, 'str2'); | |
177 expect(xzot.zot, 2); | |
178 xzot.str = 'hello'; | |
179 xzot.zot = 5; | |
180 }).then((_) => onAttributeChange(xzot)).then((_) { | |
181 expect(xzot.attributes['str'], xzot.str); | |
182 // TODO(jmesserly): the JS test seems backwards of the description text. | |
183 // Is it because it doesn't do "WebComponents.flush()"? | |
184 expect(xzot.attributes['zot'], '5', | |
185 reason: 'extendee reflect false not honored'); | |
186 }); | |
187 }); | |
188 })); | |
OLD | NEW |