| OLD | NEW |
| (Empty) |
| 1 library zone_spec; | |
| 2 | |
| 3 import '../_specs.dart'; | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 | |
| 7 main() => describe('zone', () { | |
| 8 var zone; | |
| 9 var exceptionHandler; | |
| 10 beforeEach(module((Module module) { | |
| 11 exceptionHandler = new LoggingExceptionHandler(); | |
| 12 module.value(ExceptionHandler, exceptionHandler); | |
| 13 })); | |
| 14 | |
| 15 beforeEach(inject((Logger log, ExceptionHandler eh) { | |
| 16 zone = new NgZone(); | |
| 17 zone.onTurnDone = () { | |
| 18 log('onTurnDone'); | |
| 19 }; | |
| 20 zone.onError = (e, s, ls) => eh(e, s); | |
| 21 })); | |
| 22 | |
| 23 | |
| 24 describe('exceptions', () { | |
| 25 it('should rethrow exceptions from the body and call onError', () { | |
| 26 var error; | |
| 27 zone.onError = (e, s, l) => error = e; | |
| 28 expect(() { | |
| 29 zone.run(() { | |
| 30 throw ['hello']; | |
| 31 }); | |
| 32 }).toThrow('hello'); | |
| 33 expect(error).toEqual(['hello']); | |
| 34 }); | |
| 35 | |
| 36 | |
| 37 it('should call onError for errors from scheduleMicrotask', async(inject(()
{ | |
| 38 zone.run(() { | |
| 39 scheduleMicrotask(() { | |
| 40 throw ["async exception"]; | |
| 41 }); | |
| 42 }); | |
| 43 | |
| 44 expect(exceptionHandler.errors.length).toEqual(1); | |
| 45 expect(exceptionHandler.errors[0].error).toEqual(["async exception"]); | |
| 46 }))); | |
| 47 | |
| 48 | |
| 49 it('should allow executing code outside the zone', inject(() { | |
| 50 var zone = new NgZone(); | |
| 51 var outerZone = Zone.current; | |
| 52 var ngZone; | |
| 53 var outsideZone; | |
| 54 zone.run(() { | |
| 55 ngZone = Zone.current; | |
| 56 zone.runOutsideAngular(() { | |
| 57 outsideZone = Zone.current; | |
| 58 }); | |
| 59 }); | |
| 60 | |
| 61 expect(outsideZone).toEqual(outerZone); | |
| 62 expect(ngZone.parent).toEqual((outerZone)); | |
| 63 })); | |
| 64 | |
| 65 | |
| 66 it('should rethrow exceptions from the onTurnDone and call onError when the
zone is sync', () { | |
| 67 zone.onTurnDone = () { | |
| 68 throw ["fromOnTurnDone"]; | |
| 69 }; | |
| 70 | |
| 71 expect(() { | |
| 72 zone.run(() { }); | |
| 73 }).toThrow('fromOnTurnDone'); | |
| 74 | |
| 75 expect(exceptionHandler.errors.length).toEqual(1); | |
| 76 expect(exceptionHandler.errors[0].error).toEqual(["fromOnTurnDone"]); | |
| 77 }); | |
| 78 | |
| 79 | |
| 80 it('should rethrow exceptions from the onTurnDone and call onError when the
zone is async', () { | |
| 81 var asyncRan = false; | |
| 82 | |
| 83 zone.onTurnDone = () { | |
| 84 throw ["fromOnTurnDone"]; | |
| 85 }; | |
| 86 | |
| 87 expect(() { | |
| 88 zone.run(() { | |
| 89 scheduleMicrotask(() { | |
| 90 asyncRan = true; | |
| 91 }); | |
| 92 }); | |
| 93 }).toThrow('fromOnTurnDone'); | |
| 94 | |
| 95 expect(asyncRan).toBeTruthy(); | |
| 96 expect(exceptionHandler.errors.length).toEqual(1); | |
| 97 expect(exceptionHandler.errors[0].error).toEqual(["fromOnTurnDone"]); | |
| 98 }); | |
| 99 }); | |
| 100 | |
| 101 xdescribe('long stack traces', () { | |
| 102 it('should have nice error when crossing scheduleMicrotask boundries', async
(inject(() { | |
| 103 var error; | |
| 104 var stack; | |
| 105 var longStacktrace; | |
| 106 | |
| 107 zone.onError = (e, s, f) { | |
| 108 error = e; | |
| 109 stack = s; | |
| 110 longStacktrace = f; | |
| 111 }; | |
| 112 var FRAME = new RegExp(r'.*\(.*\:(\d+):\d+\)'); | |
| 113 | |
| 114 var line = ((){ try {throw [];} catch(e, s) { return int.parse(FRAME.first
Match('$s')[1]);}})(); | |
| 115 var throwFn = () { throw ['double zonned']; }; | |
| 116 var inner = () => zone.run(throwFn); | |
| 117 var middle = () => scheduleMicrotask(inner); | |
| 118 var outer = () => scheduleMicrotask(middle); | |
| 119 zone.run(outer); | |
| 120 | |
| 121 microLeap(); | |
| 122 expect(error).toEqual(['double zonned']); | |
| 123 | |
| 124 // Not in dart2js.. | |
| 125 if ('$stack'.contains('.dart.js')) { | |
| 126 return; | |
| 127 } | |
| 128 | |
| 129 expect('$stack').toContain('zone_spec.dart:${line+1}'); | |
| 130 expect('$stack').toContain('zone_spec.dart:${line+2}'); | |
| 131 expect('$longStacktrace').toContain('zone_spec.dart:${line+3}'); | |
| 132 expect('$longStacktrace').toContain('zone_spec.dart:${line+4}'); | |
| 133 expect('$longStacktrace').toContain('zone_spec.dart:${line+5}'); | |
| 134 }))); | |
| 135 }); | |
| 136 | |
| 137 it('should call onTurnDone after a synchronous block', inject((Logger log) { | |
| 138 zone.run(() { | |
| 139 log('run'); | |
| 140 }); | |
| 141 expect(log.result()).toEqual('run; onTurnDone'); | |
| 142 })); | |
| 143 | |
| 144 | |
| 145 it('should return the body return value from run', () { | |
| 146 expect(zone.run(() { return 6; })).toEqual(6); | |
| 147 }); | |
| 148 | |
| 149 | |
| 150 it('should call onTurnDone for a scheduleMicrotask in onTurnDone', async(injec
t((Logger log) { | |
| 151 var ran = false; | |
| 152 zone.onTurnDone = () { | |
| 153 if (!ran) { | |
| 154 scheduleMicrotask(() { ran = true; log('onTurnAsync'); }); | |
| 155 } | |
| 156 log('onTurnDone'); | |
| 157 }; | |
| 158 zone.run(() { | |
| 159 log('run'); | |
| 160 }); | |
| 161 microLeap(); | |
| 162 | |
| 163 expect(log.result()).toEqual('run; onTurnDone; onTurnAsync; onTurnDone'); | |
| 164 }))); | |
| 165 | |
| 166 | |
| 167 it('should call onTurnDone for a scheduleMicrotask in onTurnDone triggered by
a scheduleMicrotask in run', async(inject((Logger log) { | |
| 168 var ran = false; | |
| 169 zone.onTurnDone = () { | |
| 170 if (!ran) { | |
| 171 scheduleMicrotask(() { ran = true; log('onTurnAsync'); }); | |
| 172 } | |
| 173 log('onTurnDone'); | |
| 174 }; | |
| 175 zone.run(() { | |
| 176 scheduleMicrotask(() { log('scheduleMicrotask'); }); | |
| 177 log('run'); | |
| 178 }); | |
| 179 microLeap(); | |
| 180 | |
| 181 expect(log.result()).toEqual('run; scheduleMicrotask; onTurnDone; onTurnAsyn
c; onTurnDone'); | |
| 182 }))); | |
| 183 | |
| 184 | |
| 185 | |
| 186 it('should call onTurnDone once after a turn', async(inject((Logger log) { | |
| 187 zone.run(() { | |
| 188 log('run start'); | |
| 189 scheduleMicrotask(() { | |
| 190 log('async'); | |
| 191 }); | |
| 192 log('run end'); | |
| 193 }); | |
| 194 microLeap(); | |
| 195 | |
| 196 expect(log.result()).toEqual('run start; run end; async; onTurnDone'); | |
| 197 }))); | |
| 198 | |
| 199 | |
| 200 it('should work for Future.value as well', async(inject((Logger log) { | |
| 201 var futureRan = false; | |
| 202 zone.onTurnDone = () { | |
| 203 if (!futureRan) { | |
| 204 new Future.value(null).then((_) { log('onTurn future'); }); | |
| 205 futureRan = true; | |
| 206 } | |
| 207 log('onTurnDone'); | |
| 208 }; | |
| 209 | |
| 210 zone.run(() { | |
| 211 log('run start'); | |
| 212 new Future.value(null) | |
| 213 .then((_) { | |
| 214 log('future then'); | |
| 215 new Future.value(null) | |
| 216 .then((_) { log('future ?'); }); | |
| 217 return new Future.value(null); | |
| 218 }) | |
| 219 .then((_) { | |
| 220 log('future ?'); | |
| 221 }); | |
| 222 log('run end'); | |
| 223 }); | |
| 224 microLeap(); | |
| 225 | |
| 226 expect(log.result()).toEqual('run start; run end; future then; future ?; fut
ure ?; onTurnDone; onTurn future; onTurnDone'); | |
| 227 }))); | |
| 228 | |
| 229 | |
| 230 it('should call onTurnDone after each turn', async(inject((Logger log) { | |
| 231 Completer a, b; | |
| 232 zone.run(() { | |
| 233 a = new Completer(); | |
| 234 b = new Completer(); | |
| 235 a.future.then((_) => log('a then')); | |
| 236 b.future.then((_) => log('b then')); | |
| 237 log('run start'); | |
| 238 }); | |
| 239 microLeap(); | |
| 240 zone.run(() { | |
| 241 a.complete(null); | |
| 242 }); | |
| 243 microLeap(); | |
| 244 zone.run(() { | |
| 245 b.complete(null); | |
| 246 }); | |
| 247 microLeap(); | |
| 248 | |
| 249 expect(log.result()).toEqual('run start; onTurnDone; a then; onTurnDone; b t
hen; onTurnDone'); | |
| 250 }))); | |
| 251 | |
| 252 | |
| 253 it('should call onTurnDone after each turn in a chain', async(inject((Logger l
og) { | |
| 254 zone.run(() { | |
| 255 log('run start'); | |
| 256 scheduleMicrotask(() { | |
| 257 log('async1'); | |
| 258 scheduleMicrotask(() { | |
| 259 log('async2'); | |
| 260 }); | |
| 261 }); | |
| 262 log('run end'); | |
| 263 }); | |
| 264 microLeap(); | |
| 265 | |
| 266 expect(log.result()).toEqual('run start; run end; async1; async2; onTurnDone
'); | |
| 267 }))); | |
| 268 | |
| 269 it('should call onTurnDone for futures created outside of run body', async(inj
ect((Logger log) { | |
| 270 var future = new Future.value(4).then((x) => new Future.value(x)); | |
| 271 zone.run(() { | |
| 272 future.then((_) => log('future then')); | |
| 273 log('zone run'); | |
| 274 }); | |
| 275 microLeap(); | |
| 276 | |
| 277 expect(log.result()).toEqual('zone run; onTurnDone; future then; onTurnDone'
); | |
| 278 }))); | |
| 279 | |
| 280 | |
| 281 it('should call onTurnDone even if there was an exception in body', async(inje
ct((Logger log) { | |
| 282 zone.onError = (e, s, l) => log('onError'); | |
| 283 expect(() => zone.run(() { | |
| 284 log('zone run'); | |
| 285 throw 'zoneError'; | |
| 286 })).toThrow('zoneError'); | |
| 287 expect(() => zone.assertInTurn()).toThrow(); | |
| 288 expect(log.result()).toEqual('zone run; onError; onTurnDone'); | |
| 289 }))); | |
| 290 | |
| 291 | |
| 292 it('should call onTurnDone even if there was an exception in scheduleMicrotask
', async(inject((Logger log) { | |
| 293 zone.onError = (e, s, l) => log('onError'); | |
| 294 zone.run(() { | |
| 295 log('zone run'); | |
| 296 scheduleMicrotask(() { | |
| 297 log('scheduleMicrotask'); | |
| 298 throw new Error(); | |
| 299 }); | |
| 300 }); | |
| 301 | |
| 302 microLeap(); | |
| 303 | |
| 304 expect(() => zone.assertInTurn()).toThrow(); | |
| 305 expect(log.result()).toEqual('zone run; scheduleMicrotask; onError; onTurnDo
ne'); | |
| 306 }))); | |
| 307 | |
| 308 it('should support assertInZone', async(() { | |
| 309 var calls = ''; | |
| 310 zone.onTurnDone = () { | |
| 311 zone.assertInZone(); | |
| 312 calls += 'done;'; | |
| 313 }; | |
| 314 zone.run(() { | |
| 315 zone.assertInZone(); | |
| 316 calls += 'sync;'; | |
| 317 scheduleMicrotask(() { | |
| 318 zone.assertInZone(); | |
| 319 calls += 'async;'; | |
| 320 }); | |
| 321 }); | |
| 322 | |
| 323 microLeap(); | |
| 324 expect(calls).toEqual('sync;async;done;'); | |
| 325 })); | |
| 326 | |
| 327 it('should throw outside of the zone', () { | |
| 328 expect(async(() { | |
| 329 zone.assertInZone(); | |
| 330 microLeap(); | |
| 331 })).toThrow(); | |
| 332 }); | |
| 333 | |
| 334 | |
| 335 it('should support assertInTurn', async(() { | |
| 336 var calls = ''; | |
| 337 zone.onTurnDone = () { | |
| 338 calls += 'done;'; | |
| 339 zone.assertInTurn(); | |
| 340 }; | |
| 341 zone.run(() { | |
| 342 calls += 'sync;'; | |
| 343 zone.assertInTurn(); | |
| 344 scheduleMicrotask(() { | |
| 345 calls += 'async;'; | |
| 346 zone.assertInTurn(); | |
| 347 }); | |
| 348 }); | |
| 349 | |
| 350 microLeap(); | |
| 351 expect(calls).toEqual('sync;async;done;'); | |
| 352 })); | |
| 353 | |
| 354 | |
| 355 it('should assertInTurn outside of the zone', () { | |
| 356 expect(async(() { | |
| 357 zone.assertInTurn(); | |
| 358 microLeap(); | |
| 359 })).toThrow('ssertion'); // Support both dart2js and the VM with half a wor
d. | |
| 360 }); | |
| 361 }); | |
| OLD | NEW |