/
watcher.test.js
141 lines (124 loc) · 3.79 KB
/
watcher.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
const path = require('path');
const ncc = global.coverage ? require("../src/index") : require("../");
const fs = require('fs');
// Based on the NodeWatchFileSystem class at:
// - https://github.com/webpack/webpack/blob/master/lib/node/NodeWatchFileSystem.js
// which in turn exposes:
// - https://www.npmjs.com/package/watchpack
class CustomWatchFileSystem {
constructor(watchStart, watchEnd) {
this.closed = false;
// paused allows the watchers to stay open for the next build
this.paused = false;
this.changeCallback = undefined;
this.watchStart = watchStart;
this.watchEnd = watchEnd;
// Webpack requires us to track this stuff
this.files = undefined;
this.dirs = undefined;
this.missing = undefined;
this.timestamps = new Map();
// this will be populated for us by ncc
this.inputFileSystem = undefined;
}
triggerChanges (changed, removed) {
if (!this.paused) {
const newTime = +Date.now();
for (const file of changed)
this.timestamps.set(file, {
safeTime: newTime + 10,
accuracy: 10,
timestamp: newTime
});
for (const file of removed)
this.timestamps.set(file, null);
for (const file of changed)
this.inputFileSystem.purge(file);
for (const file of removed)
this.inputFileSystem.purge(file);
this.changeCallback(
null,
this.timestamps,
this.timestamps,
removed
);
}
}
// This is called on every rebuild
watch (files, dirs, missing, startTime, options, changeCallback) {
this.files = new Set(files);
this.dirs = new Set(dirs);
this.missing = new Set(missing);
// empty object indicates "unknown" timestamp
// (that is, not cached)
for (const item of files)
this.timestamps.set(item, {});
for (const item of dirs)
this.timestamps.set(item, {});
// null represents "no file"
for (const item of missing)
this.timestamps.set(item, null);
this.paused = false;
this.changeCallback = changeCallback;
// ...Start watching files, dirs, mising
setImmediate(() => {
this.watchStart(files, dirs, missing);
});
return {
close: () => {
this.watchEnd();
},
pause: () => {
this.paused = true;
},
getFileTimestamps: () => {
return this.timestamps;
},
getContextTimestamps: () => {
return this.timestamps;
}
};
}
}
jest.setTimeout(30000);
it('Should support custom watch API', async () => {
let buildCnt = 0;
const buildFile = path.resolve('./test/integration/twilio.js');
await new Promise((resolve, reject) => {
const watcher = new CustomWatchFileSystem(function watchStart (files, dirs, missing) {
expect(files._set.size).toBeGreaterThan(100);
expect(missing._set.size).toBeGreaterThan(40);
if (buildCnt < 3) {
setTimeout(() => {
// NOTE: We actually have to make the change for the rebuild to happen!
fs.writeFileSync(buildFile, fs.readFileSync(buildFile).toString() + '\n');
watcher.triggerChanges([buildFile], []);
}, 100);
}
}, function watchEnd () {
resolve();
});
console.time('First Build');
const { handler, rebuild, close } = ncc(buildFile, {
assetBuilds: true,
watch: watcher
});
handler(({ err, code, map, assets, permissions }) => {
if (err) return reject(err);
buildCnt++;
if (buildCnt === 1) {
console.timeEnd('First Build');
}
else {
console.timeEnd('Watched Build');
}
if (buildCnt === 3) {
close();
fs.writeFileSync(buildFile, fs.readFileSync(buildFile).toString().slice(0, -2));
}
});
rebuild(() => {
console.time('Watched Build');
});
});
});