-
-
Notifications
You must be signed in to change notification settings - Fork 591
/
testUtils.js
170 lines (143 loc) · 4.07 KB
/
testUtils.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
"use strict";
const path = require("path");
const execa = require("execa");
const { sync: spawnSync } = execa;
const { Writable } = require("readable-stream");
const WEBPACK_PATH = path.resolve(__dirname, "../bin/cli.js");
/**
* Description
*
* @param {*} testCase The path to folder that contains the webpack.config.js
* @param {*} args Array of arguments to pass to webpack
* @returns {Object} The webpack output
*/
function run(testCase, args = []) {
const cwd = path.resolve(testCase);
const outputPath = path.resolve(testCase, "bin");
const argsWithOutput = args.concat("--output-path", outputPath);
const result = spawnSync(WEBPACK_PATH, argsWithOutput, {
cwd,
reject: false
});
return result;
}
function runWatch(testCase, args = []) {
const cwd = path.resolve(testCase);
const outputPath = path.resolve(testCase, "bin");
const argsWithOutput = args.concat("--output-path", outputPath);
return new Promise(resolve => {
const watchPromise = execa(WEBPACK_PATH, argsWithOutput, {
cwd,
reject: false
});
watchPromise.stdout.pipe(
new Writable({
write(chunk, encoding, callback) {
const output = chunk.toString("utf8");
if (output.includes("Time")) {
watchPromise.kill();
}
callback();
}
})
);
watchPromise.then(result => {
resolve(result);
});
});
}
function extractSummary(stdout) {
if (stdout === "") {
return "";
}
return stdout
.split("\n")
.filter(line => !line.includes("Hash"))
.filter(line => !line.includes("Version"))
.filter(line => !line.includes("Time"))
.filter(line => !line.includes("Built at"))
.join("\n");
}
/**
* @typedef {Object} Config
* @property {string} name - name of config
* @property {string} hash - hash of config
*
* @typedef {Object} HashInfo
* @property {string} hash - global hash value
* @property {Array.<Config>} config
*/
/**
* Description
*
* @param {string} stdout stdout of generic webpack output
* @returns {HashInfo} - an object containing hash-info
* @throws Will throw an error if {@link stdout}
* - is empty
* - does not contain Hash
* - does not contain Hash
* - if multiple configs then, count(hash) !== count(Child) + 1 (+1 is for global hash)
*
*/
function extractHash(stdout) {
if (stdout === "") {
throw new Error("stdout is empty");
}
let hashArray = stdout.match(/Hash.*/gm);
// If logs are full of errors and we don't find hash
if (!hashArray) {
throw new Error(
`could not find hash in the stdout
OUTPUT: ${stdout}`
);
}
hashArray = hashArray.map(hashLine => hashLine.replace(/Hash:(.*)/, "$1").trim());
const hashInfo = {
hash: hashArray[0],
config: []
};
// Multiple config were found
if (hashArray.length > 1) {
let childArray = stdout.match(/Child.*/gm);
if (!childArray) {
throw new Error(
`could not find config in the stdout
OUTPUT: ${stdout}`
);
}
childArray = childArray.map(childLine => childLine.replace(/Child(.*):/, "$1").trim());
// We don't need global hash anymore
// so we'll remove it to maintain 1:1 parity between config and hash
hashArray.shift();
if (hashArray.length !== childArray.length) {
throw new Error(`The stdout is corrupted. Hash count and config count do not match.
OUTPUT: ${stdout}`);
}
const configCount = childArray.length;
for (let configIdx = 0; configIdx < configCount; configIdx++) {
hashInfo["config"].push({
name: childArray[configIdx],
hash: hashArray[configIdx]
});
}
}
return hashInfo;
}
/*eslint valid-jsdoc: ["error", { "requireReturn": false }]*/
/**
*
* @param {*} testCase - testCase directory
* @param {*} file - file relative to testCase
* @param {*} data - data to append
* @throws - throw an Error if file does not exist
*/
function appendDataIfFileExists(testCase, file, data) {
const { existsSync, appendFileSync } = require("fs");
const filePath = path.resolve(testCase, file);
if (existsSync(filePath)) {
appendFileSync(filePath, data);
} else {
throw new Error(`Oops! ${filePath} does not exist!`);
}
}
module.exports = { run, runWatch, extractHash, extractSummary, appendDataIfFileExists };