-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
/
utils.js
175 lines (153 loc) · 4.53 KB
/
utils.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
171
172
173
174
175
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
'use strict';
import type {Path} from 'types/Config';
const {spawnSync} = require('child_process');
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const rimraf = require('rimraf');
const run = (cmd: string, cwd?: Path) => {
const args = cmd.split(/\s/).slice(1);
const spawnOptions = {cwd};
const result = spawnSync(cmd.split(/\s/)[0], args, spawnOptions);
if (result.status !== 0) {
const message = `
ORIGINAL CMD: ${cmd}
STDOUT: ${result.stdout && result.stdout.toString()}
STDERR: ${result.stderr && result.stderr.toString()}
STATUS: ${result.status}
ERROR: ${result.error && result.error.toString()}
`;
throw new Error(message);
}
result.stdout = result.stdout && result.stdout.toString();
result.stderr = result.stderr && result.stderr.toString();
return result;
};
const linkJestPackage = (packageName: string, cwd: Path) => {
const packagesDir = path.resolve(__dirname, '../packages');
const packagePath = path.resolve(packagesDir, packageName);
const destination = path.resolve(cwd, 'node_modules/');
run(`mkdir -p ${destination}`);
return run(`ln -sf ${packagePath} ${destination}`);
};
const fileExists = (filePath: Path) => {
try {
fs.accessSync(filePath, fs.F_OK);
return true;
} catch (e) {
return false;
}
};
const makeTemplate = (str: string): ((values?: Array<any>) => string) => {
return (values: ?Array<any>) => {
return str.replace(/\$(\d+)/g, (match, number) => {
if (!Array.isArray(values)) {
throw new Error('Array of values must be passed to the template.');
}
return values[number - 1];
});
};
};
const cleanup = (directory: string) => rimraf.sync(directory);
/**
* Creates a nested directory with files and their contents
* writeFiles(
* '/home/tmp',
* {
* 'package.json': '{}',
* '__tests__/test.test.js': 'test("lol")',
* }
* );
*/
const writeFiles = (directory: string, files: {[filename: string]: string}) => {
mkdirp.sync(directory);
Object.keys(files).forEach(fileOrPath => {
const filePath = fileOrPath.split('/'); // ['tmp', 'a.js']
const filename = filePath.pop(); // filepath becomes dirPath (no filename)
if (filePath.length) {
mkdirp.sync(path.join.apply(path, [directory].concat(filePath)));
}
fs.writeFileSync(
path.resolve.apply(path, [directory].concat(filePath, [filename])),
files[fileOrPath],
);
});
};
const copyDir = (src: string, dest: string) => {
const srcStat = fs.lstatSync(src);
if (srcStat.isDirectory()) {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest);
}
fs.readdirSync(src).map(filePath => {
return copyDir(path.join(src, filePath), path.join(dest, filePath));
});
} else {
fs.writeFileSync(dest, fs.readFileSync(src));
}
};
const createEmptyPackage = (
directory: Path,
packageJson?: {[keys: string]: any},
) => {
const DEFAULT_PACKAGE_JSON = {
description: 'THIS IS AN AUTOGENERATED FILE AND SHOULD NOT BE ADDED TO GIT',
jest: {
testEnvironment: 'node',
},
};
mkdirp.sync(directory);
packageJson || (packageJson = DEFAULT_PACKAGE_JSON);
fs.writeFileSync(
path.resolve(directory, 'package.json'),
JSON.stringify(packageJson, null, 2),
);
};
const extractSummary = (stdout: string) => {
const match = stdout.match(
/Test Suites:.*\nTests.*\nSnapshots.*\nTime.*(\nRan all test suites)*.*\n*$/gm,
);
if (!match) {
throw new Error(
`
Could not find test summary in the output.
OUTPUT:
${stdout}
`,
);
}
const summary = match[0]
.replace(/\d*\.?\d+m?s/g, '<<REPLACED>>')
.replace(/, estimated <<REPLACED>>/g, '');
const rest = cleanupStackTrace(
// remove all timestamps
stdout.slice(0, -match[0].length).replace(/\s*\(.*ms\)/gm, ''),
);
return {rest, summary};
};
// different versions of Node print different stack traces. This function
// unifies their output to make it possible to snapshot them.
// TODO: Remove when we drop support for node 4
const cleanupStackTrace = (output: string) => {
return output.replace(/^.*at.*[\s][\(]?(\S*\:\d*\:\d*).*$/gm, ' at $1');
};
module.exports = {
cleanup,
cleanupStackTrace,
copyDir,
createEmptyPackage,
extractSummary,
fileExists,
linkJestPackage,
makeTemplate,
run,
writeFiles,
};