angular.mock library
Properties
String depth #
String depth = ''
Functions
dynamic sync(Function fn) #
Enforces synchronous code. Any calls to runAsync inside of 'sync' will throw an exception.
sync(Function fn) => () { dartAsync.runZoned(fn, zoneSpecification: new dartAsync.ZoneSpecification( scheduleMicrotask: (_, __, ___, asyncFn) => throw ['runAsync called from sync function.'], createTimer: (_, __, ____, Duration duration, void f()) => throw ['Timer created from sync function.'], createPeriodicTimer: (_, __, ___, Duration period, void f(dartAsync.Timer timer)) => throw ['periodic Timer created from sync function.'] )); };
dynamic async(Function fn) #
Captures all runAsync calls inside of a function.
Typically used within a test: it('should be async', async(() { ... }));
async(Function fn) => () { _noMoreAsync = false; _asyncErrors = []; _timerQueue = []; var zoneSpec = new dartAsync.ZoneSpecification( scheduleMicrotask: (_, __, ___, asyncFn) { if (_noMoreAsync) { throw ['runAsync called after noMoreAsync()']; } else { _asyncQueue.add(asyncFn); } }, createTimer: (_, __, ____, Duration duration, void f()) => _createTimer(f, duration, false), createPeriodicTimer: (_, __, ___, Duration period, void f(dartAsync.Timer timer)) => _createTimer(f, period, true), handleUncaughtError: (_, __, ___, e) => _asyncErrors.add(e) ); dartAsync.runZoned(() { fn(); microLeap(); }, zoneSpecification: zoneSpec); _asyncErrors.forEach((e) { throw "During runZoned: $e. Stack:\n${dartAsync.getAttachedStackTrace(e)}"; }); if (!_timerQueue.isEmpty && _timerQueue.any((_TimerSpec spec) => spec.isActive)) { throw ["${_timerQueue.where((_TimerSpec spec) => spec.isActive).length} " "active timer(s) are still in the queue."]; } };
dynamic noMoreAsync() #
Causes runAsync calls to throw exceptions.
This function is useful while debugging async tests: the exception is thrown from the runAsync call-site instead later in the test.
noMoreAsync() { _noMoreAsync = true; }
dynamic clockTick({int days: 0, int hours: 0, int minutes: 0, int seconds: 0, int milliseconds: 0, int microseconds: 0}) #
Simulates a clock tick by running any scheduled timers. Can only be used in async tests.Clock tick will call microLeap to process the microtask queue before each timer callback.
Note: microtasks scheduled form the last timer are not going to be processed.
Example:
it('should run queued timer after sufficient clock ticks', async(() {
bool timerRan = false;
new Timer(new Duration(milliseconds: 10), () => timerRan = true);
clockTick(milliseconds: 9);
expect(timerRan).toBeFalsy();
clockTick(milliseconds: 1);
expect(timerRan).toBeTruthy();
}));
it('should run periodic timer', async(() {
int timerRan = 0;
new Timer.periodic(new Duration(milliseconds: 10), (_) => timerRan++);
clockTick(milliseconds: 9);
expect(timerRan).toBe(0);
clockTick(milliseconds: 1);
expect(timerRan).toBe(1);
clockTick(milliseconds: 30);
expect(timerRan).toBe(4);
}));
clockTick({int days: 0, int hours: 0, int minutes: 0, int seconds: 0, int milliseconds: 0, int microseconds: 0}) { var tickDuration = new Duration(days: days, hours: hours, minutes: minutes, seconds: seconds, milliseconds: milliseconds, microseconds: microseconds); var queue = _timerQueue; var remainingTimers = []; _timerQueue = []; queue.forEach((_TimerSpec spec) { if (!spec.isActive) return; // Skip over inactive timers. if (spec.periodic) { // We always add back the periodic timer unless it's cancelled. remainingTimers.add(spec); // Ignore ZERO duration ticks for periodic timers. if (tickDuration == Duration.ZERO) return; spec.elapsed += tickDuration; // Run the timer as many times as the timer priod fits into the tick. while (spec.elapsed >= spec.duration) { spec.elapsed -= spec.duration; microLeap(); spec.fn(spec); } } else { spec.duration -= tickDuration; if (spec.duration <= Duration.ZERO) { microLeap(); spec.fn(); } else { remainingTimers.add(spec); } } }); // Remaining timers should come before anything else scheduled after them. _timerQueue.insertAll(0, remainingTimers); }
dynamic microLeap() #
Runs any queued up async calls and any async calls queued with running microLeap. Example:
it('should run async code', async(() {
var thenRan = false;
new Future.value('s').then((_) { thenRan = true; });
expect(thenRan).toBe(false);
microLeap();
expect(thenRan).toBe(true);
}));
it('should run chained thens', async(() {
var log = [];
new Future.value('s')
.then((_) { log.add('firstThen'); })
.then((_) { log.add('2ndThen'); });
expect(log.join(' ')).toEqual('');
microLeap();
expect(log.join(' ')).toEqual('firstThen 2ndThen');
}));
microLeap() { while (!_asyncQueue.isEmpty) { // copy the queue as it may change. var toRun = new List.from(_asyncQueue); _asyncQueue = []; // TODO: Support the case where multiple exceptions are thrown. // e.g. with a throwNextException() method. assert(_asyncErrors.isEmpty); toRun.forEach((fn) => fn()); if (!_asyncErrors.isEmpty) { var e = _asyncErrors.removeAt(0); throw ['Async error', e, dartAsync.getAttachedStackTrace(e)]; } } }
dynamic STRINGIFY(obj) #
STRINGIFY(obj) { if (obj is List) { var out = []; obj.forEach((i) => out.add(STRINGIFY(i))); return '[${out.join(", ")}]'; } else if (obj is Comment) { return '<!--${obj.text}-->'; } else if (obj is Element) { return obj.outerHtml; } else if (obj is String) { return '"$obj"'; } else { return obj.toString(); } }
dynamic dump([p1, p2, p3, p4, p5, p6, p7, p8, p9, p10]) #
dump([p1, p2, p3, p4, p5, p6, p7, p8, p9, p10]) { var log = []; if (p1 != null) log.add(STRINGIFY(p1)); if (p2 != null) log.add(STRINGIFY(p2)); if (p3 != null) log.add(STRINGIFY(p3)); if (p4 != null) log.add(STRINGIFY(p4)); if (p5 != null) log.add(STRINGIFY(p5)); if (p6 != null) log.add(STRINGIFY(p6)); if (p7 != null) log.add(STRINGIFY(p7)); if (p8 != null) log.add(STRINGIFY(p8)); if (p9 != null) log.add(STRINGIFY(p9)); if (p10 != null) log.add(STRINGIFY(p10)); js.scoped(() { (js.context as dynamic).console.log(log.join(', ')); }); }
dynamic MARK(name) #
MARK(name) { dump('$depth$name'); }
dynamic LEAVE(name) #
LEAVE(name) { depth = depth.substring(0, depth.length -2); dump('${depth}LEAVE: $name'); }
dynamic ENTER(name) #
ENTER(name) { dump('${depth}ENTER: $name'); depth = depth + ' '; }