OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2014 Google Inc. All rights reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style |
| 5 * license that can be found in the LICENSE file or at |
| 6 * https://developers.google.com/open-source/licenses/bsd |
| 7 */ |
| 8 |
| 9 library charted.test.transition; |
| 10 |
| 11 import 'dart:async'; |
| 12 import 'dart:html' show document, Element; |
| 13 import 'package:charted/core/utils.dart'; |
| 14 import 'package:charted/interpolators/interpolators.dart'; |
| 15 import 'package:charted/selection/selection.dart'; |
| 16 import 'package:charted/selection/transition.dart'; |
| 17 import 'package:unittest/unittest.dart'; |
| 18 |
| 19 transitionTests() { |
| 20 const TIME_BIAS = 50; |
| 21 String markup = |
| 22 '<div class="transition-container">' |
| 23 '<div class="delay-100"></div>' |
| 24 '<div class="delay-500"></div>' |
| 25 '<div class="delay-callback"></div>' |
| 26 '<div class="delay-callback"></div>' |
| 27 '<div class="delay-callback"></div>' |
| 28 '<div class="duration-100"></div>' |
| 29 '<div class="duration-callback"></div>' |
| 30 '<div class="duration-callback"></div>' |
| 31 '<div class="duration-callback"></div>' |
| 32 '<div class="attr-100"></div>' |
| 33 '<div class="attr-callback"></div>' |
| 34 '<div class="attr-callback"></div>' |
| 35 '<div class="attr-callback"></div>' |
| 36 '<div class="style-callback"></div>' |
| 37 '<div class="style-callback"></div>' |
| 38 '<div class="style-callback"></div>' |
| 39 '<div class="attr-tween"></div>' |
| 40 '<div class="attr-tween"></div>' |
| 41 '<div class="attr-tween"></div>' |
| 42 '<div class="style-tween"></div>' |
| 43 '<div class="style-tween"></div>' |
| 44 '<div class="style-tween"></div>' |
| 45 '<div class="chained-transition"></div>' |
| 46 '<div class="transition-select">' |
| 47 '<div class="select-item"></div>' |
| 48 '</div>' |
| 49 '<div class="transition-select-all">' |
| 50 '<div class="select-item"></div>' |
| 51 '<div class="select-item"></div>' |
| 52 '<div class="select-item"></div>' |
| 53 '</div>' |
| 54 '</div>'; |
| 55 |
| 56 Element root; |
| 57 SelectionScope scope; |
| 58 |
| 59 setup() { |
| 60 root = new Element.html(markup); |
| 61 document.documentElement.append(root); |
| 62 scope = new SelectionScope.selector('.transition-container'); |
| 63 } |
| 64 |
| 65 teardown() { |
| 66 root.remove(); |
| 67 } |
| 68 |
| 69 setUp(setup); |
| 70 tearDown(teardown); |
| 71 |
| 72 void checkColor(e, color, [bool equal = true]) { |
| 73 if (color == null) { |
| 74 expect(e.attributes['style'], isNull); |
| 75 } else if (equal) { |
| 76 expect(e.attributes['style'], equals('background-color: ${color};')); |
| 77 } else { |
| 78 expect(e.attributes['style'] |
| 79 .compareTo('background-color: ${color};') == 0, isFalse); |
| 80 } |
| 81 } |
| 82 |
| 83 void checkHeight(e, height, [bool equal = true]) { |
| 84 if (height == null) { |
| 85 expect(e.attributes['height'], isNull); |
| 86 } else if (equal) { |
| 87 expect(e.attributes['height'], equals('${height}')); |
| 88 } else { |
| 89 expect(e.attributes['height'].compareTo('${height}') == 0, isFalse); |
| 90 } |
| 91 } |
| 92 |
| 93 test('Transition.delay delays specific time before transition', () { |
| 94 Selection transition1 = scope.select('.delay-100'); |
| 95 transition1.transition() |
| 96 ..style('background-color', '#ffffff') |
| 97 ..delay(100); |
| 98 new Timer(new Duration(milliseconds:100 - TIME_BIAS), expectAsync(() { |
| 99 transition1.each((d, i, Element e) { |
| 100 checkColor(e, null); |
| 101 }); |
| 102 })); |
| 103 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 104 transition1.each((d, i, Element e) { |
| 105 checkColor(e, 'rgb(255, 255, 255)'); |
| 106 }); |
| 107 })); |
| 108 Selection transition2 = scope.select('.delay-500'); |
| 109 transition2.transition() |
| 110 ..style('background-color', '#ffffff') |
| 111 ..delay(500); |
| 112 new Timer(new Duration(milliseconds:500 - TIME_BIAS), expectAsync(() { |
| 113 transition2.each((d, i, Element e) { |
| 114 checkColor(e, null); |
| 115 }); |
| 116 })); |
| 117 new Timer(new Duration(milliseconds:500 + TIME_BIAS), expectAsync(() { |
| 118 transition2.each((d, i, Element e) { |
| 119 checkColor(e, 'rgb(255, 255, 255)'); |
| 120 }); |
| 121 })); |
| 122 }); |
| 123 |
| 124 test('Transition.delayWithCallback delays specific time by callback', () { |
| 125 Selection transition = scope.selectAll('.delay-callback'); |
| 126 transition.transition() |
| 127 ..style('background-color', '#ffffff') |
| 128 ..delayWithCallback((d, i, e) => (i + 1) * 100); |
| 129 new Timer(new Duration(milliseconds:100 - TIME_BIAS), expectAsync(() { |
| 130 transition.each((d, i, Element e) { |
| 131 checkColor(e, null); |
| 132 }); |
| 133 })); |
| 134 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 135 transition.each((d, i, Element e) { |
| 136 if (i > 0) checkColor(e, null); |
| 137 else checkColor(e, 'rgb(255, 255, 255)'); |
| 138 }); |
| 139 })); |
| 140 new Timer(new Duration(milliseconds:200 + TIME_BIAS), expectAsync(() { |
| 141 transition.each((d, i, Element e) { |
| 142 if (i > 1) checkColor(e, null); |
| 143 else checkColor(e, 'rgb(255, 255, 255)'); |
| 144 }); |
| 145 })); |
| 146 new Timer(new Duration(milliseconds:300 + TIME_BIAS), expectAsync(() { |
| 147 transition.each((d, i, Element e) { |
| 148 checkColor(e, 'rgb(255, 255, 255)'); |
| 149 }); |
| 150 })); |
| 151 }); |
| 152 |
| 153 test('Transition.duration sets the duration of transition', () { |
| 154 Selection transition = scope.select('.duration-100'); |
| 155 transition |
| 156 .style('background-color', '#000000'); |
| 157 transition.transition() |
| 158 ..style('background-color', '#ffffff') |
| 159 ..duration(100); |
| 160 transition.each((d, i, Element e) { |
| 161 checkColor(e, 'rgb(0, 0, 0)'); |
| 162 }); |
| 163 new Timer(new Duration(milliseconds:50), expectAsync(() { |
| 164 transition.each((d, i, Element e) { |
| 165 checkColor(e, 'rgb(0, 0, 0)', false); |
| 166 checkColor(e, 'rgb(255, 255, 255)', false); |
| 167 }); |
| 168 })); |
| 169 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 170 transition.each((d, i, Element e) { |
| 171 checkColor(e, 'rgb(255, 255, 255)'); |
| 172 }); |
| 173 })); |
| 174 }); |
| 175 |
| 176 test('Transition.durationWithCallback sets duration by callback', () { |
| 177 Selection transition = scope.selectAll('.duration-callback'); |
| 178 transition |
| 179 .style('background-color', '#000000'); |
| 180 transition.transition() |
| 181 ..style('background-color', '#ffffff') |
| 182 ..durationWithCallback((d, i, e) => (i + 1) * 100); |
| 183 transition.each((d, i, Element e) { |
| 184 checkColor(e, 'rgb(0, 0, 0)'); |
| 185 }); |
| 186 new Timer(new Duration(milliseconds:100 - TIME_BIAS), expectAsync(() { |
| 187 transition.each((d, i, Element e) { |
| 188 checkColor(e, 'rgb(0, 0, 0)', false); |
| 189 checkColor(e, 'rgb(255, 255, 255)', false); |
| 190 }); |
| 191 })); |
| 192 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 193 transition.each((d, i, Element e) { |
| 194 if (i < 1) { |
| 195 checkColor(e, 'rgb(255, 255, 255)'); |
| 196 } else { |
| 197 checkColor(e, 'rgb(0, 0, 0)', false); |
| 198 checkColor(e, 'rgb(255, 255, 255)', false); |
| 199 } |
| 200 }); |
| 201 })); |
| 202 new Timer(new Duration(milliseconds:200 + TIME_BIAS), expectAsync(() { |
| 203 transition.each((d, i, Element e) { |
| 204 if (i < 2) { |
| 205 checkColor(e, 'rgb(255, 255, 255)'); |
| 206 } else { |
| 207 checkColor(e, 'rgb(0, 0, 0)', false); |
| 208 checkColor(e, 'rgb(255, 255, 255)', false); |
| 209 } |
| 210 }); |
| 211 })); |
| 212 new Timer(new Duration(milliseconds:300 + TIME_BIAS), expectAsync(() { |
| 213 transition.each((d, i, Element e) { |
| 214 checkColor(e, 'rgb(255, 255, 255)'); |
| 215 }); |
| 216 })); |
| 217 }); |
| 218 |
| 219 test('Transition.attr sets the attribute of transition', () { |
| 220 Selection transition = scope.select('.attr-100'); |
| 221 transition.attr('height', '0'); |
| 222 transition.transition() |
| 223 ..attr('height', '100') |
| 224 ..duration(100); |
| 225 transition.each((d, i, Element e) { |
| 226 checkHeight(e, 0); |
| 227 }); |
| 228 new Timer(new Duration(milliseconds:50), expectAsync(() { |
| 229 transition.each((d, i, Element e) { |
| 230 checkHeight(e, 0, false); |
| 231 checkHeight(e, 100, false); |
| 232 }); |
| 233 })); |
| 234 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 235 transition.each((d, i, Element e) { |
| 236 checkHeight(e, 100); |
| 237 }); |
| 238 })); |
| 239 }); |
| 240 |
| 241 test('Transition.attrWithCallback sets the attribute by callback', () { |
| 242 Selection transition = scope.selectAll('.attr-callback'); |
| 243 transition.attr('height', '0'); |
| 244 transition.transition() |
| 245 ..attrWithCallback('height', (d, i, e) => (i + 1) * 100) |
| 246 ..duration(100); |
| 247 transition.each((d, i, Element e) { |
| 248 checkHeight(e, 0); |
| 249 }); |
| 250 new Timer(new Duration(milliseconds:50), expectAsync(() { |
| 251 transition.each((d, i, Element e) { |
| 252 checkHeight(e, 0, false); |
| 253 checkHeight(e, (i + 1) * 100, false); |
| 254 }); |
| 255 })); |
| 256 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 257 transition.each((d, i, Element e) { |
| 258 checkHeight(e, (i + 1) * 100); |
| 259 }); |
| 260 })); |
| 261 }); |
| 262 |
| 263 test('Transition.styleWithCallback sets the style by callback', () { |
| 264 Selection transition = scope.selectAll('.style-callback'); |
| 265 transition.style('background-color', 'rgb(0, 0, 0)'); |
| 266 var colors = ['rgb(255, 0, 0);', 'rgb(0, 255, 0);', 'rgb(0, 0, 255);']; |
| 267 transition.transition() |
| 268 ..styleWithCallback('background-color', (d, i, e) => colors[i]) |
| 269 ..duration(100); |
| 270 transition.each((d, i, Element e) { |
| 271 checkColor(e, 'rgb(0, 0, 0)'); |
| 272 }); |
| 273 new Timer(new Duration(milliseconds:50), expectAsync(() { |
| 274 transition.each((d, i, Element e) { |
| 275 checkColor(e, 'rgb(0, 0, 0)', false); |
| 276 checkColor(e, colors[i], false); |
| 277 }); |
| 278 })); |
| 279 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 280 transition.each((d, i, Element e) { |
| 281 checkColor(e, colors[i], false); |
| 282 }); |
| 283 })); |
| 284 }); |
| 285 |
| 286 test('Transition.attrTween transitions the value of the attribute with ' |
| 287 'the specified name according to the specified tween function', () { |
| 288 Selection transition = scope.selectAll('.attr-tween'); |
| 289 transition.attr('height', '0px'); |
| 290 transition.transition() |
| 291 ..attrTween('height', (d, i, attr) => |
| 292 interpolateString(attr, ((i + 1) * 100).toString() + 'px')) |
| 293 ..duration(100); |
| 294 transition.each((d, i, Element e) { |
| 295 checkHeight(e, '0px'); |
| 296 }); |
| 297 new Timer(new Duration(milliseconds:50), expectAsync(() { |
| 298 transition.each((d, i, Element e) { |
| 299 checkHeight(e, '0px', false); |
| 300 checkHeight(e, '${(i + 1) * 100}.0px', false); |
| 301 }); |
| 302 })); |
| 303 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 304 transition.each((d, i, Element e) { |
| 305 checkHeight(e, '${(i + 1) * 100}.0px'); |
| 306 }); |
| 307 })); |
| 308 }); |
| 309 |
| 310 test('Transition.styleTween transitions the value of the CSS style property ' |
| 311 'with the specified name according to the specified tween function', () { |
| 312 Selection transition = scope.selectAll('.style-tween'); |
| 313 transition.style('background-color', 'rgb(0, 0, 0)'); |
| 314 var colors = ['rgb(255, 0, 0);', 'rgb(0, 255, 0);', 'rgb(0, 0, 255);']; |
| 315 transition.transition() |
| 316 ..styleTween('background-color', (d, i, style) => |
| 317 interpolateString(style, colors[i])) |
| 318 ..duration(100); |
| 319 transition.each((d, i, Element e) { |
| 320 checkColor(e, 'rgb(0, 0, 0)'); |
| 321 }); |
| 322 new Timer(new Duration(milliseconds:50), expectAsync(() { |
| 323 transition.each((d, i, Element e) { |
| 324 checkColor(e, 'rgb(0, 0, 0)', false); |
| 325 checkColor(e, colors[i], false); |
| 326 }); |
| 327 })); |
| 328 new Timer(new Duration(milliseconds:100 + TIME_BIAS), expectAsync(() { |
| 329 transition.each((d, i, Element e) { |
| 330 checkColor(e, colors[i], false); |
| 331 }); |
| 332 })); |
| 333 }); |
| 334 |
| 335 test('Transition.transition implements chained transition', () { |
| 336 Selection transition = scope.select('.chained-transition'); |
| 337 transition.attr('height', '0'); |
| 338 Transition t = transition.transition(); |
| 339 t..duration(500) |
| 340 ..attr('height', '10000'); |
| 341 var t2 = t.transition(); |
| 342 t2.attr('height', '1000'); |
| 343 |
| 344 new Timer(new Duration(milliseconds:200), expectAsync(() { |
| 345 transition.each((d, i, Element e) { |
| 346 var height = num.parse(e.attributes['height']); |
| 347 expect(height > 0, isTrue); |
| 348 expect(height < 7500, isTrue); |
| 349 }); |
| 350 })); |
| 351 new Timer(new Duration(milliseconds:500), expectAsync(() { |
| 352 transition.each((d, i, Element e) { |
| 353 var height = num.parse(e.attributes['height']); |
| 354 expect(height > 7500, isTrue); |
| 355 }); |
| 356 })); |
| 357 |
| 358 new Timer(new Duration(milliseconds:1000 + TIME_BIAS), expectAsync(() { |
| 359 transition.each((d, i, Element e) { |
| 360 var height = num.parse(e.attributes['height']); |
| 361 expect(height == 1000, isTrue); |
| 362 }); |
| 363 })); |
| 364 }); |
| 365 |
| 366 test('Transition.select selects the first descendant element ' |
| 367 'that matches the specified selector string', () { |
| 368 Selection transition = scope.select('.transition-select'); |
| 369 transition.select('.select-item') |
| 370 ..attr('height', '100'); |
| 371 transition.select('.select-item').each((d, i, Element e) { |
| 372 var height = num.parse(e.attributes['height']); |
| 373 expect(height, equals(100)); |
| 374 }); |
| 375 }); |
| 376 |
| 377 test('Transition.selectAll selects all descendant elements ' |
| 378 'that match the specified selector string', () { |
| 379 Selection transition = scope.select('.transition-select-all'); |
| 380 transition.selectAll('.select-item') |
| 381 ..attr('height', '100'); |
| 382 transition.selectAll('.select-item').each((d, i, Element e) { |
| 383 var height = num.parse(e.attributes['height']); |
| 384 expect(height, equals(100)); |
| 385 }); |
| 386 }); |
| 387 } |
OLD | NEW |