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 + ' ';
}