Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 591f6f5

Browse files
committed
test(watch): additional buildUpdate queue tests
additional buildUpdate queue tests
1 parent 0cbfb12 commit 591f6f5

File tree

2 files changed

+246
-5
lines changed

2 files changed

+246
-5
lines changed

src/watch.spec.ts

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,246 @@ describe('watch', () => {
416416
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileFive)[0]).toEqual(changedFileFive);
417417
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileSix)[0]).toEqual(changedFileSix);
418418
expect(buildUpdateSpy.calls.mostRecent().args[1]).toEqual(context);
419+
});
420+
421+
});
422+
423+
it('should run buildUpdate on the queued files even if the first build update fails', () => {
424+
const changedFileOne: ChangedFile = {
425+
event: 'change',
426+
ext: '.ts',
427+
filePath: '/some/fake/path/that/doesnt/matter.ts'
428+
};
429+
const changedFileTwo: ChangedFile = {
430+
event: 'change',
431+
ext: '.ts',
432+
filePath: '/some/fake/path/that/doesnt/matter2.ts'
433+
};
434+
435+
const changedFileThree: ChangedFile = {
436+
event: 'change',
437+
ext: '.ts',
438+
filePath: '/some/fake/path/that/doesnt/matter3.ts'
439+
};
440+
const changedFileFour: ChangedFile = {
441+
event: 'change',
442+
ext: '.ts',
443+
filePath: '/some/fake/path/that/doesnt/matter4.ts'
444+
};
445+
446+
const changedFileFive: ChangedFile = {
447+
event: 'change',
448+
ext: '.ts',
449+
filePath: '/some/fake/path/that/doesnt/matter5.ts'
450+
};
451+
const changedFileSix: ChangedFile = {
452+
event: 'change',
453+
ext: '.ts',
454+
filePath: '/some/fake/path/that/doesnt/matter6.ts'
455+
};
456+
457+
const originalChangedFiles = [changedFileOne, changedFileTwo];
458+
const secondSetOfChangedFiles = [changedFileThree, changedFileFour];
459+
const ThirdSetOfChangedFiles = [changedFileTwo, changedFileFour, changedFileFive, changedFileSix];
460+
const context = {};
461+
462+
let firstPromiseReject: Function = null;
463+
const firstPromise = new Promise((resolve, reject) => {
464+
firstPromiseReject = reject;
465+
});
466+
spyOn(watch, watch.queueOrRunBuildUpdate.name).and.callThrough();
467+
const buildUpdateSpy = spyOn(build, build.buildUpdate.name).and.callFake((changedFiles: ChangedFile[], context: BuildContext) => {
468+
if (changedFiles === originalChangedFiles) {
469+
return firstPromise;
470+
} else {
471+
return Promise.resolve();
472+
}
473+
});
474+
475+
// call the original
476+
expect(watch.buildUpdatePromise).toBeFalsy();
477+
const promise = watch.queueOrRunBuildUpdate(originalChangedFiles, context);
478+
expect(watch.buildUpdatePromise).toBeTruthy();
479+
expect(watch.queuedChangedFileMap.size).toEqual(0);
480+
expect(build.buildUpdate).toHaveBeenCalledTimes(1);
481+
482+
// okay, call again and it should be queued now
483+
watch.queueOrRunBuildUpdate(secondSetOfChangedFiles, context);
484+
expect(watch.buildUpdatePromise).toBeTruthy();
485+
expect(watch.queuedChangedFileMap.size).toEqual(2);
486+
expect(watch.queuedChangedFileMap.get(changedFileThree.filePath)).toEqual(changedFileThree);
487+
expect(watch.queuedChangedFileMap.get(changedFileFour.filePath)).toEqual(changedFileFour);
488+
expect(build.buildUpdate).toHaveBeenCalledTimes(1);
489+
490+
// okay, let's queue some more
491+
watch.queueOrRunBuildUpdate(ThirdSetOfChangedFiles, context);
492+
expect(watch.buildUpdatePromise).toBeTruthy();
493+
expect(watch.queuedChangedFileMap.size).toEqual(5);
494+
expect(watch.queuedChangedFileMap.get(changedFileTwo.filePath)).toEqual(changedFileTwo);
495+
expect(watch.queuedChangedFileMap.get(changedFileThree.filePath)).toEqual(changedFileThree);
496+
expect(watch.queuedChangedFileMap.get(changedFileFour.filePath)).toEqual(changedFileFour);
497+
expect(watch.queuedChangedFileMap.get(changedFileFive.filePath)).toEqual(changedFileFive);
498+
expect(watch.queuedChangedFileMap.get(changedFileSix.filePath)).toEqual(changedFileSix);
499+
expect(build.buildUpdate).toHaveBeenCalledTimes(1);
500+
501+
firstPromiseReject();
502+
return promise.then(() => {
503+
expect(watch.buildUpdatePromise).toBeFalsy();
504+
expect(watch.queuedChangedFileMap.size).toEqual(0);
505+
expect(build.buildUpdate).toHaveBeenCalledTimes(2);
506+
expect(buildUpdateSpy.calls.first().args[0]).toEqual(originalChangedFiles);
507+
expect(buildUpdateSpy.calls.first().args[1]).toEqual(context);
508+
expect(buildUpdateSpy.calls.mostRecent().args[0].length).toEqual(5);
509+
// make sure the array contains the elements that we expect it to
510+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileTwo)[0]).toEqual(changedFileTwo);
511+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileThree)[0]).toEqual(changedFileThree);
512+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileFour)[0]).toEqual(changedFileFour);
513+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileFive)[0]).toEqual(changedFileFive);
514+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileSix)[0]).toEqual(changedFileSix);
515+
expect(buildUpdateSpy.calls.mostRecent().args[1]).toEqual(context);
516+
});
517+
});
419518

519+
it('should handle multiple queueing and unqueuing events aka advanced test', () => {
520+
const changedFileOne: ChangedFile = {
521+
event: 'change',
522+
ext: '.ts',
523+
filePath: '/some/fake/path/that/doesnt/matter.ts'
524+
};
525+
const changedFileTwo: ChangedFile = {
526+
event: 'change',
527+
ext: '.ts',
528+
filePath: '/some/fake/path/that/doesnt/matter2.ts'
529+
};
530+
531+
const changedFileThree: ChangedFile = {
532+
event: 'change',
533+
ext: '.ts',
534+
filePath: '/some/fake/path/that/doesnt/matter3.ts'
535+
};
536+
const changedFileFour: ChangedFile = {
537+
event: 'change',
538+
ext: '.ts',
539+
filePath: '/some/fake/path/that/doesnt/matter4.ts'
540+
};
541+
542+
const changedFileFive: ChangedFile = {
543+
event: 'change',
544+
ext: '.ts',
545+
filePath: '/some/fake/path/that/doesnt/matter5.ts'
546+
};
547+
const changedFileSix: ChangedFile = {
548+
event: 'change',
549+
ext: '.ts',
550+
filePath: '/some/fake/path/that/doesnt/matter6.ts'
551+
};
552+
553+
const originalChangedFiles = [changedFileOne, changedFileTwo];
554+
const secondSetOfChangedFiles = [changedFileThree, changedFileFour];
555+
const thirdSetOfChangedFiles = [changedFileTwo, changedFileFour, changedFileFive, changedFileSix];
556+
const fourthSetOfChangedFiles = [changedFileOne, changedFileThree];
557+
const fifthSetOfChangedFiles = [changedFileFour, changedFileFive, changedFileSix];
558+
559+
const context = {};
560+
561+
let firstPromiseResolve: Function = null;
562+
let secondPromiseResolve: Function = null;
563+
let thirdPromiseResolve: Function = null;
564+
const firstPromise = new Promise((resolve, reject) => {
565+
firstPromiseResolve = resolve;
566+
});
567+
const secondPromise = new Promise((resolve, reject) => {
568+
secondPromiseResolve = resolve;
569+
});
570+
const thirdPromise = new Promise((resolve, reject) => {
571+
thirdPromiseResolve = resolve;
572+
});
573+
574+
spyOn(watch, watch.queueOrRunBuildUpdate.name).and.callThrough();
575+
const buildUpdateSpy = spyOn(build, build.buildUpdate.name).and.callFake((changedFiles: ChangedFile[], context: BuildContext) => {
576+
if (changedFiles === originalChangedFiles) {
577+
return firstPromise;
578+
} else if (changedFiles.length === 5) {
579+
// hardcode the length for now as it's easier to detect which array it'll be
580+
return secondPromise;
581+
} else {
582+
return thirdPromise;
583+
}
584+
});
585+
586+
// call the original
587+
expect(watch.buildUpdatePromise).toBeFalsy();
588+
const promise = watch.queueOrRunBuildUpdate(originalChangedFiles, context);
589+
expect(watch.buildUpdatePromise).toBeTruthy();
590+
expect(watch.queuedChangedFileMap.size).toEqual(0);
591+
expect(build.buildUpdate).toHaveBeenCalledTimes(1);
592+
expect(buildUpdateSpy.calls.first().args[0]).toEqual(originalChangedFiles);
593+
expect(buildUpdateSpy.calls.first().args[1]).toEqual(context);
594+
595+
// okay, call again and it should be queued now
596+
watch.queueOrRunBuildUpdate(secondSetOfChangedFiles, context);
597+
expect(watch.buildUpdatePromise).toBeTruthy();
598+
expect(watch.queuedChangedFileMap.size).toEqual(2);
599+
expect(watch.queuedChangedFileMap.get(changedFileThree.filePath)).toEqual(changedFileThree);
600+
expect(watch.queuedChangedFileMap.get(changedFileFour.filePath)).toEqual(changedFileFour);
601+
expect(build.buildUpdate).toHaveBeenCalledTimes(1);
602+
603+
// okay, let's queue some more
604+
watch.queueOrRunBuildUpdate(thirdSetOfChangedFiles, context);
605+
expect(watch.buildUpdatePromise).toBeTruthy();
606+
expect(watch.queuedChangedFileMap.size).toEqual(5);
607+
expect(watch.queuedChangedFileMap.get(changedFileTwo.filePath)).toEqual(changedFileTwo);
608+
expect(watch.queuedChangedFileMap.get(changedFileThree.filePath)).toEqual(changedFileThree);
609+
expect(watch.queuedChangedFileMap.get(changedFileFour.filePath)).toEqual(changedFileFour);
610+
expect(watch.queuedChangedFileMap.get(changedFileFive.filePath)).toEqual(changedFileFive);
611+
expect(watch.queuedChangedFileMap.get(changedFileSix.filePath)).toEqual(changedFileSix);
612+
expect(build.buildUpdate).toHaveBeenCalledTimes(1);
613+
614+
firstPromiseResolve();
615+
616+
return firstPromise.then(() => {
617+
expect(build.buildUpdate).toHaveBeenCalledTimes(2);
618+
expect(buildUpdateSpy.calls.mostRecent().args[0].length).toEqual(5);
619+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileTwo)[0]).toEqual(changedFileTwo);
620+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileThree)[0]).toEqual(changedFileThree);
621+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileFour)[0]).toEqual(changedFileFour);
622+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileFive)[0]).toEqual(changedFileFive);
623+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileSix)[0]).toEqual(changedFileSix);
624+
expect(buildUpdateSpy.calls.mostRecent().args[1]).toEqual(context);
625+
626+
// okay, give it more changes so it queues that stuff up
627+
// also do some assertions homie
628+
watch.queueOrRunBuildUpdate(fourthSetOfChangedFiles, context);
629+
expect(watch.buildUpdatePromise).toBeTruthy();
630+
expect(watch.queuedChangedFileMap.size).toEqual(2);
631+
expect(watch.queuedChangedFileMap.get(changedFileOne.filePath)).toEqual(changedFileOne);
632+
expect(watch.queuedChangedFileMap.get(changedFileThree.filePath)).toEqual(changedFileThree);
633+
634+
// cool beans yo, go ahead and resolve another promise
635+
secondPromiseResolve();
636+
return secondPromise;
637+
}).then(() => {
638+
expect(build.buildUpdate).toHaveBeenCalledTimes(3);
639+
expect(buildUpdateSpy.calls.mostRecent().args[0].length).toEqual(2);
640+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileOne)[0]).toEqual(changedFileOne);
641+
expect(buildUpdateSpy.calls.mostRecent().args[0].concat().filter((changedFile: ChangedFile) => changedFile === changedFileThree)[0]).toEqual(changedFileThree);
642+
643+
// okay, give it more changes so it queues that stuff up
644+
// also do some assertions homie
645+
watch.queueOrRunBuildUpdate(fifthSetOfChangedFiles, context);
646+
expect(watch.buildUpdatePromise).toBeTruthy();
647+
expect(watch.queuedChangedFileMap.size).toEqual(3);
648+
expect(watch.queuedChangedFileMap.get(changedFileFour.filePath)).toEqual(changedFileFour);
649+
expect(watch.queuedChangedFileMap.get(changedFileFive.filePath)).toEqual(changedFileFive);
650+
expect(watch.queuedChangedFileMap.get(changedFileSix.filePath)).toEqual(changedFileSix);
651+
652+
// cool beans yo, go ahead and resolve another promise
653+
thirdPromiseResolve();
654+
return thirdPromise;
655+
656+
}).then(() => {
657+
// return the original promise just to make sure everything is chained together
658+
return promise;
420659
});
421660
});
422661
});

src/watch.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,22 +231,24 @@ export function queueOrRunBuildUpdate(changedFiles: ChangedFile[], context: Buil
231231
// there is not an active build going going on
232232
// clear out any queued file changes, and run the build
233233
queuedChangedFileMap.clear();
234-
const buildUpdateComplete = () => {
234+
235+
const buildUpdateCompleteCallback: () => Promise<any> = () => {
235236
// the update is complete, so check if there are pending updates that need to be run
236237
buildUpdatePromise = null;
237238
if (queuedChangedFileMap.size > 0) {
238239
const queuedChangeFileList: ChangedFile[] = [];
239240
queuedChangedFileMap.forEach(changedFile => {
240241
queuedChangeFileList.push(changedFile);
241242
});
242-
queueOrRunBuildUpdate(queuedChangeFileList, context);
243+
return queueOrRunBuildUpdate(queuedChangeFileList, context);
243244
}
245+
return Promise.resolve();
244246
};
245247

246-
buildUpdatePromise = buildTask.buildUpdate(changedFiles, context).then(buildUpdateComplete).catch((err: Error) => {
247-
buildUpdateComplete();
248+
buildUpdatePromise = buildTask.buildUpdate(changedFiles, context);
249+
return buildUpdatePromise.then(buildUpdateCompleteCallback).catch((err: Error) => {
250+
return buildUpdateCompleteCallback();
248251
});
249-
return buildUpdatePromise;
250252
}
251253
}
252254

0 commit comments

Comments
 (0)