UNPKG

schedulejs

Version:

Schedule tasks, meetings, appointments, etc

335 lines (256 loc) 12.3 kB
var schedule = require('../../index'), later = require('later'), should = require('should'), util = require('util'); describe('Schedule', function() { // project schedule setup var projSched = {schedules: [{h_a: [8], h_b: [18]}]}; // set to use local time schedule.date.localTime(); describe('forward pass with vanilla tasks', function() { it('should schedule a single task at first available time', function() { var tasks = [ {id: 'A', duration: 100} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 8, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); s.A.duration.should.eql(100); }); it('should schedule dependent tasks after one another', function() { var tasks = [ {id: 'A', duration: 100}, {id: 'B', duration: 100, dependsOn: ['A']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 8, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); s.A.duration.should.eql(100); s.B.earlyStart.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); s.B.earlyFinish.should.eql((new Date(2013, 2, 21, 11, 20, 0)).getTime()); s.B.duration.should.eql(100); }); it('should schedule sibling tasks in parallel', function() { var tasks = [ {id: 'A', duration: 100}, {id: 'B', duration: 100, dependsOn: ['A']}, {id: 'C', duration: 100, dependsOn: ['A']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.B.earlyStart.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); s.B.earlyFinish.should.eql((new Date(2013, 2, 21, 11, 20, 0)).getTime()); s.B.duration.should.eql(100); s.C.earlyStart.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); s.C.earlyFinish.should.eql((new Date(2013, 2, 21, 11, 20, 0)).getTime()); s.C.duration.should.eql(100); }); it('should wait for all dependencies to complete before scheduling dependent task', function() { var tasks = [ {id: 'A', duration: 100}, {id: 'B', duration: 100, dependsOn: ['A']}, {id: 'C', duration: 200, dependsOn: ['A']}, {id: 'D', duration: 100, dependsOn: ['B', 'C']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.D.earlyStart.should.eql((new Date(2013, 2, 21, 13, 0, 0)).getTime()); s.D.earlyFinish.should.eql((new Date(2013, 2, 21, 14, 40, 0)).getTime()); s.D.duration.should.eql(100); }); it('should fail to schedule tasks with circular dependencies', function() { var tasks = [ {id: 'A', duration: 100}, {id: 'B', duration: 100, dependsOn: ['A', 'C']}, {id: 'C', duration: 200, dependsOn: ['D']}, {id: 'D', duration: 100, dependsOn: ['B']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate); should.not.exist(s.scheduledTasks.B); should.not.exist(s.scheduledTasks.C); should.not.exist(s.scheduledTasks.D); s.failedTasks.length.should.eql(3); s.success.should.eql(false); }); it('should split tasks across multiple days when needed', function() { var tasks = [ {id: 'A', duration: 720} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.schedule.length.should.eql(2); s.A.schedule[0].duration.should.eql(600); s.A.schedule[1].duration.should.eql(120); s.A.earlyStart.should.eql((new Date(2013, 2, 21, 8, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 22, 10, 0, 0)).getTime()); s.A.duration.should.eql(720); }); it('should go to next range when at end of range', function() { var tasks = [ {id: 'A', duration: 600}, {id: 'B', duration: 120, dependsOn: ['A']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 8, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 18, 0, 0)).getTime()); s.A.duration.should.eql(600); s.B.earlyStart.should.eql((new Date(2013, 2, 22, 8, 0, 0)).getTime()); s.B.earlyFinish.should.eql((new Date(2013, 2, 22, 10, 0, 0)).getTime()); s.B.duration.should.eql(120); }); }); describe('backward pass with vanilla tasks', function() { it('should set late finish to early finish for single task', function() { var tasks = [ {id: 'A', duration: 100} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.lateFinish.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); }); it('should set late finish for dependent tasks', function() { var tasks = [ {id: 'A', duration: 100}, {id: 'B', duration: 100, dependsOn: ['A']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.lateFinish.should.eql((new Date(2013, 2, 21, 9, 40, 0)).getTime()); s.B.lateFinish.should.eql((new Date(2013, 2, 21, 11, 20, 0)).getTime()); }); it('should set late finish to latest leaf node', function() { var tasks = [ {id: 'A', duration: 60}, {id: 'B', duration: 60, dependsOn: ['A']}, {id: 'C', duration: 120, dependsOn: ['A']}, {id: 'D', duration: 60, dependsOn: ['C']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.lateFinish.should.eql((new Date(2013, 2, 21, 9, 0, 0)).getTime()); s.B.lateFinish.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); s.C.lateFinish.should.eql((new Date(2013, 2, 21, 11, 0, 0)).getTime()); s.D.lateFinish.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); }); it('should set float amount in minutes', function() { var tasks = [ {id: 'A', duration: 60}, {id: 'B', duration: 60, dependsOn: ['A']}, {id: 'C', duration: 120, dependsOn: ['A']}, {id: 'D', duration: 60, dependsOn: ['C']} ], startDate = new Date(2013, 2, 21); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.floatAmt.should.eql(0); s.B.floatAmt.should.eql(120); s.C.floatAmt.should.eql(0); s.D.floatAmt.should.eql(0); }); }); describe('minimum schedule length', function() { it('should not schedule a task shorter than minimum schedule length', function() { var tasks = [ {id: 'A', duration: 240, minSchedule: 120} ], startDate = new Date(2013, 2, 21, 17, 0, 0); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.schedule.length.should.eql(1); s.A.schedule[0].duration.should.eql(240); s.A.earlyStart.should.eql((new Date(2013, 2, 22, 8, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 22, 12, 0, 0)).getTime()); s.A.duration.should.eql(240); }); it('should split tasks if minSchedule is met', function() { var tasks = [ {id: 'A', duration: 240, minSchedule: 120} ], startDate = new Date(2013, 2, 21, 16, 0, 0); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.schedule.length.should.eql(2); s.A.schedule[0].duration.should.eql(120); s.A.schedule[1].duration.should.eql(120); s.A.earlyStart.should.eql((new Date(2013, 2, 21, 16, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 22, 10, 0, 0)).getTime()); s.A.duration.should.eql(240); }); }); describe('task priority', function() { it('should schedule higher priority tasks first', function() { var tasks = [ {id: 'A', duration: 120, resources: ['A'], priority: 0}, {id: 'B', duration: 120, resources: ['A'], priority: 100}, {id: 'C', duration: 120, resources: ['A'], priority: 50} ], startDate = new Date(2013, 2, 21, 0, 0, 0); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 14, 0, 0)).getTime()); s.B.earlyStart.should.eql((new Date(2013, 2, 21, 8, 0, 0)).getTime()); s.B.earlyFinish.should.eql((new Date(2013, 2, 21, 10, 0, 0)).getTime()); s.C.earlyStart.should.eql((new Date(2013, 2, 21, 10, 0, 0)).getTime()); s.C.earlyFinish.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); }); it('should maintain dependency ordering', function() { var tasks = [ {id: 'A', duration: 120, resources: ['A'], priority: 0}, {id: 'B', duration: 120, dependsOn: ['A'], resources: ['A'], priority: 100}, {id: 'C', duration: 120, dependsOn: ['A'], resources: ['A'], priority: 150} ], startDate = new Date(2013, 2, 21, 0, 0, 0); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 8, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 10, 0, 0)).getTime()); s.B.earlyStart.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); s.B.earlyFinish.should.eql((new Date(2013, 2, 21, 14, 0, 0)).getTime()); s.C.earlyStart.should.eql((new Date(2013, 2, 21, 10, 0, 0)).getTime()); s.C.earlyFinish.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); }); }); describe('task schedules', function() { it('should only schedule tasks when available', function() { var tasks = [ {id: 'A', duration: 120, available: {schedules: [{h_a: [12]}]}} ], startDate = new Date(2013, 2, 21, 0, 0, 0); var s = schedule.create(tasks, [], projSched, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 14, 0, 0)).getTime()); }); it('should fail to schedule tasks that will never be available', function() { var tasks = [ {id: 'A', duration: 120, available: {schedules: [{fd_b: [100]}]}} ], startDate = new Date(2013, 2, 21, 0, 0, 0); var s = schedule.create(tasks, [], projSched, startDate); s.failedTasks.should.eql(['A']); s.success.should.eql(false); }); it('should fail to schedule tasks with an invalid schedule', function() { var tasks = [ {id: 'A', duration: 120, available: { schedules: [{h: [5,6]}], exceptions: [{h: [5,6]}] } } ], startDate = new Date(2013, 2, 21, 0, 0, 0); var s = schedule.create(tasks, [], projSched, startDate); s.failedTasks.should.eql(['A']); s.success.should.eql(false); }); it('should work if project schedule is null', function() { var tasks = [ {id: 'A', duration: 120, available: {schedules: [{h_a: [12]}]}} ], startDate = new Date(2013, 2, 21, 0, 0, 0); var s = schedule.create(tasks, null, null, startDate).scheduledTasks; s.A.earlyStart.should.eql((new Date(2013, 2, 21, 12, 0, 0)).getTime()); s.A.earlyFinish.should.eql((new Date(2013, 2, 21, 14, 0, 0)).getTime()); }); }); });