It was confusing because the test.unit.dart task does ignore the initial, and the logger was hardcoded to always ignore the first task, leading to the appearance that a run was happening twice for no reason. Also, fixed the "fake ignoreInitial" handling to not rely on a fake event, which is not necessary. Closes #2101
		
			
				
	
	
		
			177 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |