180 lines
4.6 KiB
JavaScript
180 lines
4.6 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
var rewire = require('rewire');
|
|
|
|
describe('watch()', function() {
|
|
var timeout;
|
|
var watch;
|
|
var watcher;
|
|
var unmock;
|
|
|
|
beforeEach(function() {
|
|
timeout = mockTimeout();
|
|
var watchModule = rewire('./watch');
|
|
unmock = watchModule.__set__(timeout.mocks);
|
|
watch = watchModule.__get__('watch');
|
|
});
|
|
|
|
afterEach(function() {
|
|
// Shouldn't really be necessary, but...
|
|
if (watcher) {
|
|
watcher.close();
|
|
watcher = null;
|
|
}
|
|
unmock();
|
|
expect(timeout.pending).toBe(0);
|
|
timeout = null;
|
|
});
|
|
|
|
|
|
it('should fire callback once for events which occur within `delay` window', function() {
|
|
var cb = jasmine.createSpy('callback');
|
|
watcher = watch('./$$fake_path/**/*', {delay: 10, log: false}, cb);
|
|
|
|
watcher._emit('add', './$$fake_path/test.txt');
|
|
timeout.flush(9);
|
|
expect(cb).not.toHaveBeenCalled();
|
|
|
|
watcher._emit('change', './$$fake_path/test.txt');
|
|
watcher._emit('add', './$$fake_path/test2.txt');
|
|
watcher._emit('change', './$$fake_path/test2.txt');
|
|
watcher._emit('add', './$$fake_path/test3.txt');
|
|
watcher._emit('change', './$$fake_path/test3.txt');
|
|
expect(cb).not.toHaveBeenCalled();
|
|
|
|
timeout.flush(1);
|
|
expect(cb.calls.count()).toBe(1);
|
|
});
|
|
|
|
|
|
it('should trigger callback if events are collected during task running', function() {
|
|
var calls = 0;
|
|
function cb(done) {
|
|
if (++calls !== 1) return done();
|
|
|
|
watcher._emit('change', './$$fake_path/test1.txt');
|
|
watcher._emit('change', './$$fake_path/test2.txt');
|
|
|
|
// Before the done callback, there are no pending timer events
|
|
expect(timeout.pending).toBe(0);
|
|
done();
|
|
|
|
// Afterwards, there is one
|
|
expect(timeout.pending).toBe(1);
|
|
}
|
|
|
|
var watcher = watch('./$$fake_path/**/*', {delay: 10, log: false}, cb);
|
|
|
|
watcher._emit('change', './$$fake_path/test1.txt');
|
|
expect(timeout.pending).toBe(1);
|
|
expect(calls).toBe(0);
|
|
|
|
timeout.flush(10);
|
|
expect(calls).toBe(2);
|
|
});
|
|
|
|
|
|
it('should continue to trigger callbacks if task throws', function() {
|
|
var calls = 0;
|
|
spyOn(console, 'log');
|
|
function cb(done) {
|
|
calls += 1;
|
|
if (calls === 1) throw new Error('oops!');
|
|
done();
|
|
}
|
|
|
|
var watcher = watch('./$$fake_path/**/*', {delay: 10, log: false}, cb);
|
|
|
|
watcher._emit('change', './$$fake_path/test1.txt');
|
|
timeout.flush();
|
|
expect(calls).toBe(1);
|
|
expect(console.log).toHaveBeenCalledWith('Watch task error:', 'Error: oops!');
|
|
|
|
watcher._emit('change', './$$fake_path/test2.txt');
|
|
timeout.flush();
|
|
expect(calls).toBe(2);
|
|
});
|
|
|
|
|
|
it('should cancel pending callback if FSWatcher is closed', function() {
|
|
var cb = jasmine.createSpy('callback');
|
|
var watcher = watch('./$$fake_path/**/*', {delay: 10, log: false}, cb);
|
|
|
|
watcher._emit('change', './$$fake_path/test1.txt');
|
|
expect(timeout.pending).toBe(1);
|
|
expect(cb).not.toHaveBeenCalled();
|
|
|
|
watcher.close();
|
|
expect(timeout.pending).toBe(0);
|
|
});
|
|
|
|
|
|
it('should cancel followup pending callback if FSWatcher is closed during task', function() {
|
|
var calls = 0;
|
|
function cb(done) {
|
|
if (++calls !== 1) return done();
|
|
|
|
watcher._emit('change', './$$fake_path/test2.txt');
|
|
done();
|
|
expect(timeout.pending).toBe(1);
|
|
watcher.close();
|
|
expect(timeout.pending).toBe(0);
|
|
}
|
|
|
|
var watcher = watch('./$$fake_path/**/*', {delay: 10, log: false}, cb);
|
|
watcher._emit('change', './$$fake_path/test1.txt');
|
|
|
|
timeout.flush(10);
|
|
|
|
expect(calls).toBe(1);
|
|
});
|
|
});
|
|
|
|
|
|
// setTimeout/clearTimeout mocking, mostly stolen from angular-mocks.js
|
|
function mockTimeout() {
|
|
var events = [];
|
|
var id = 0;
|
|
var now = 0;
|
|
|
|
return {
|
|
mocks: {setTimeout: mockSetTimeout, clearTimeout: mockClearTimeout},
|
|
flush: flush, get pending() { return events.length; }
|
|
};
|
|
|
|
function mockSetTimeout(fn, delay) {
|
|
delay = delay || 0;
|
|
events.push({time: now + delay, fn: fn, id: id});
|
|
events.sort(function(a, b) { return a.time - b.time; });
|
|
return id++;
|
|
}
|
|
|
|
function mockClearTimeout(id) {
|
|
for (var i = 0; i < events.length; ++i) {
|
|
if (events[i].id === id) {
|
|
events.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function flush(delay) {
|
|
if (delay !== undefined)
|
|
now += delay;
|
|
else if (events.length)
|
|
now = events[events.length - 1].time;
|
|
else
|
|
throw new Error('No timer events registered');
|
|
|
|
while (events.length && events[0].time <= now) {
|
|
events.shift().fn();
|
|
}
|
|
}
|
|
}
|