[task scheduler] Mock Date.now for testing

This should make screenshots from puppeteer tests consistent.

Change-Id: I1092442ee727001ef368ca051ac63b7153e0016d
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/329159
Commit-Queue: Eric Boren <borenet@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/task_scheduler/modules/job-search-sk/job-search-sk-demo.ts b/task_scheduler/modules/job-search-sk/job-search-sk-demo.ts
index 0d6d5dc..22b0cd1 100644
--- a/task_scheduler/modules/job-search-sk/job-search-sk-demo.ts
+++ b/task_scheduler/modules/job-search-sk/job-search-sk-demo.ts
@@ -1,7 +1,10 @@
 import './index';
 
-import { FakeTaskSchedulerService } from '../rpc-mock';
+import { FakeTaskSchedulerService, fakeNow } from '../rpc-mock';
 import { JobSearchSk } from './job-search-sk';
 
+// Override the current date to keep puppeteer tests consistent.
+Date.now = () => fakeNow;
+
 const ele = <JobSearchSk>document.querySelector('job-search-sk')!;
 ele.rpc = new FakeTaskSchedulerService();
diff --git a/task_scheduler/modules/job-sk/job-sk-demo.ts b/task_scheduler/modules/job-sk/job-sk-demo.ts
index 3601a9d..f55e6f4 100644
--- a/task_scheduler/modules/job-sk/job-sk-demo.ts
+++ b/task_scheduler/modules/job-sk/job-sk-demo.ts
@@ -1,7 +1,10 @@
-import { FakeTaskSchedulerService, job2 } from '../rpc-mock';
+import { FakeTaskSchedulerService, job2, fakeNow } from '../rpc-mock';
 import './index';
 import { JobSk } from './job-sk';
 
+// Override the current date to keep puppeteer tests consistent.
+Date.now = () => fakeNow;
+
 const ele = <JobSk>document.querySelector('job-sk')!;
 ele.rpc = new FakeTaskSchedulerService();
 ele.jobID = job2.id;
diff --git a/task_scheduler/modules/job-sk/job-sk.ts b/task_scheduler/modules/job-sk/job-sk.ts
index b7a2ba6..a7b8511 100644
--- a/task_scheduler/modules/job-sk/job-sk.ts
+++ b/task_scheduler/modules/job-sk/job-sk.ts
@@ -257,7 +257,7 @@
     const start = new Date(this.job.createdAt!);
     const end = this.job.finishedAt
       ? new Date(this.job.finishedAt)
-      : new Date();
+      : new Date(Date.now()); // Use Date.now so that it can be mocked.
     this.duration = diffDate(start.getTime(), end.getTime());
     const rs = this.job.repoState!;
     this.revisionLink = `${rs.repo}/+show/${rs.revision}`;
diff --git a/task_scheduler/modules/job-timeline-sk/job-timeline-sk-demo.ts b/task_scheduler/modules/job-timeline-sk/job-timeline-sk-demo.ts
index a560352..2849335 100644
--- a/task_scheduler/modules/job-timeline-sk/job-timeline-sk-demo.ts
+++ b/task_scheduler/modules/job-timeline-sk/job-timeline-sk-demo.ts
@@ -1,6 +1,9 @@
 import './index';
 import { JobTimelineSk } from './job-timeline-sk';
-import { job1, task0, task1, task2, task3, task4 } from '../rpc-mock';
+import { job1, task0, task1, task2, task3, task4, fakeNow } from '../rpc-mock';
+
+// Override the current date to keep puppeteer tests consistent.
+Date.now = () => fakeNow;
 
 const ele = <JobTimelineSk>document.querySelector('job-timeline-sk')!;
 ele.draw(job1, [task0, task1, task2, task3, task4], []);
diff --git a/task_scheduler/modules/job-timeline-sk/job-timeline-sk.ts b/task_scheduler/modules/job-timeline-sk/job-timeline-sk.ts
index 4186235..edda91b 100644
--- a/task_scheduler/modules/job-timeline-sk/job-timeline-sk.ts
+++ b/task_scheduler/modules/job-timeline-sk/job-timeline-sk.ts
@@ -12,7 +12,7 @@
 function ts(tsStr: string) {
   // If the timestamp is zero-ish, return the current datetime.
   if (Date.parse(tsStr) <= 0) {
-    return new Date();
+    return new Date(Date.now()); // Use Date.now so that it can be mocked.
   }
   return new Date(tsStr);
 }
@@ -47,7 +47,7 @@
       // becomes multiple blocks, indicating the download and upload overhead
       // as well as the run time itself.
       let lastBlockEnd = createTs;
-      const makeBlock = function(label: string, end: string, color: string) {
+      const makeBlock = function (label: string, end: string, color: string) {
         const block: Block = {
           label: label,
           start: lastBlockEnd,
@@ -58,16 +58,28 @@
         lane!.blocks.push(block);
       };
       if (t.startedAt) {
-        makeBlock("pending", t.startedAt, "#e69f00");
+        makeBlock('pending', t.startedAt, '#e69f00');
       }
       if (t.stats) {
         const startTs = ts(t.startedAt!).getTime();
         const finishTs = ts(t.finishedAt!).getTime();
-        makeBlock("overhead", new Date(startTs + 1000*parseFloat(t.stats.downloadOverheadS)).toString(), "#d55e00");
-        makeBlock("running", new Date(finishTs - 1000*parseFloat(t.stats.uploadOverheadS)).toString(), "#0072b2");
-        makeBlock("overhead", t.finishedAt!, "#d55e00");
+        makeBlock(
+          'overhead',
+          new Date(
+            startTs + 1000 * parseFloat(t.stats.downloadOverheadS)
+          ).toString(),
+          '#d55e00'
+        );
+        makeBlock(
+          'running',
+          new Date(
+            finishTs - 1000 * parseFloat(t.stats.uploadOverheadS)
+          ).toString(),
+          '#0072b2'
+        );
+        makeBlock('overhead', t.finishedAt!, '#d55e00');
       } else {
-        makeBlock("running", t.finishedAt || "", "#0072b2");
+        makeBlock('running', t.finishedAt || '', '#0072b2');
       }
     }
 
@@ -84,6 +96,6 @@
     }
     draw(this, data);
   }
-};
+}
 
 define('job-timeline-sk', JobTimelineSk);
diff --git a/task_scheduler/modules/rpc-mock/fake-data.ts b/task_scheduler/modules/rpc-mock/fake-data.ts
index 0078cd8..312c9f2 100644
--- a/task_scheduler/modules/rpc-mock/fake-data.ts
+++ b/task_scheduler/modules/rpc-mock/fake-data.ts
@@ -1,6 +1,10 @@
 import { Job, Task } from '../rpc';
 import { TaskStatus, JobStatus, RepoState, SkipTaskRule } from '../rpc/rpc';
 
+// This is an arbitrary date which happens to be after all of the other
+// timestamps listed in this file.
+export const fakeNow = new Date('2019-11-10T13:56:44.572122663Z').getTime();
+
 export const job1ID = 'aYwjrLWysQRUW2lGFQvR';
 export const job2ID = 'bYwjrLWysQRUW2lGFQvX';
 
@@ -273,8 +277,8 @@
 export const job2: Job = {
   buildbucketBuildId: 8921090193851453000,
   buildbucketLeaseKey: 0,
-  createdAt: new Date('2016-10-10T13:56:44.572122663Z').toUTCString(),
-  dbModifiedAt: new Date('2016-10-10T19:56:44.572122663Z').toString(),
+  createdAt: new Date('2019-10-10T13:56:44.572122663Z').toUTCString(),
+  dbModifiedAt: new Date('2019-10-10T19:56:44.572122663Z').toString(),
   dependencies: [
     {
       task: 'F',
@@ -307,7 +311,7 @@
   name: 'ABCDEF',
   priority: '0.8',
   repoState: repoState,
-  requestedAt: new Date('2016-10-10T13:55:44.572122663Z').toUTCString(),
+  requestedAt: new Date('2019-10-10T13:55:44.572122663Z').toUTCString(),
   status: JobStatus.JOB_STATUS_IN_PROGRESS,
   tasks: [
     {
diff --git a/task_scheduler/modules/task-sk/task-sk-demo.ts b/task_scheduler/modules/task-sk/task-sk-demo.ts
index b11e8fe..55cb0ca 100644
--- a/task_scheduler/modules/task-sk/task-sk-demo.ts
+++ b/task_scheduler/modules/task-sk/task-sk-demo.ts
@@ -1,7 +1,10 @@
-import { task2, FakeTaskSchedulerService } from '../rpc-mock';
+import { task2, FakeTaskSchedulerService, fakeNow } from '../rpc-mock';
 import './index';
 import { TaskSk } from './task-sk';
 
+// Override the current date to keep puppeteer tests consistent.
+Date.now = () => fakeNow;
+
 const ele = <TaskSk>document.querySelector('task-sk')!;
 ele.rpc = new FakeTaskSchedulerService();
 ele.taskID = task2.id;
diff --git a/task_scheduler/modules/task-sk/task-sk.ts b/task_scheduler/modules/task-sk/task-sk.ts
index 83fe6df..fa7f965 100644
--- a/task_scheduler/modules/task-sk/task-sk.ts
+++ b/task_scheduler/modules/task-sk/task-sk.ts
@@ -211,7 +211,7 @@
       const start = new Date(this.task.createdAt!);
       const end = this.task.finishedAt
         ? new Date(this.task.finishedAt)
-        : new Date();
+        : new Date(Date.now()); // Use Date.now so that it can be mocked.
       this.duration = diffDate(start.getTime(), end.getTime());
       const rs = this.task.taskKey!.repoState!;
       this.revisionLink = `${rs.repo}/+show/${rs.revision}`;