UNPKG

11 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = get;
7exports.multiple = multiple;
8exports.readFile = readFile;
9exports.resolveOptionPluginOrPreset = resolveOptionPluginOrPreset;
10var _semver = require("semver");
11var _path = require("path");
12var _fs = require("fs");
13var _url = require("url");
14var _module = require("module");
15const nodeVersion = _semver.clean(process.version.slice(1));
16function humanize(val, noext) {
17 if (noext) val = _path.basename(val, _path.extname(val));
18 return val.replace(/-/g, " ");
19}
20function tryResolve(module) {
21 try {
22 return require.resolve(module);
23 } catch (e) {
24 return null;
25 }
26}
27function assertDirectory(loc) {
28 if (!_fs.statSync(loc).isDirectory()) {
29 throw new Error(`Expected ${loc} to be a directory.`);
30 }
31}
32function shouldIgnore(name, ignore) {
33 if (ignore && ignore.indexOf(name) >= 0) {
34 return true;
35 }
36 const ext = _path.extname(name);
37 const base = _path.basename(name, ext);
38 return name[0] === "." || ext === ".md" || base === "LICENSE" || base === "options" || name === "package.json";
39}
40const EXTENSIONS = [".js", ".mjs", ".ts", ".tsx", ".cts", ".mts", ".vue"];
41const JSON_AND_EXTENSIONS = [".json", ...EXTENSIONS];
42function checkFile(loc, allowJSON, matchedLoc) {
43 const ext = _path.extname(loc);
44 const extensions = allowJSON ? JSON_AND_EXTENSIONS : EXTENSIONS;
45 if (!extensions.includes(ext)) {
46 throw new Error(`Unsupported input extension: ${loc}`);
47 }
48 if (!matchedLoc) {
49 return loc;
50 } else {
51 throw new Error(`Found conflicting file matches: ${matchedLoc},${loc}`);
52 }
53}
54function pushTask(taskName, taskDir, suite, suiteName) {
55 var _taskOpts$externalHel;
56 const taskDirStats = _fs.statSync(taskDir);
57 let actualLoc, expectLoc, execLoc, execLocAlias, taskOptsLoc, stdoutLoc, stderrLoc, sourceMapLoc, sourceMapVisualLoc, inputSourceMap;
58 const taskOpts = JSON.parse(JSON.stringify(suite.options));
59 if (taskDirStats.isDirectory()) {
60 var _actualLoc, _execLoc, _expectLoc;
61 const files = _fs.readdirSync(taskDir);
62 for (const file of files) {
63 const loc = _path.join(taskDir, file);
64 const name = _path.basename(file, _path.extname(file));
65 switch (name) {
66 case "input":
67 actualLoc = checkFile(loc, false, actualLoc);
68 break;
69 case "exec":
70 execLoc = checkFile(loc, false, execLoc);
71 break;
72 case "output":
73 expectLoc = checkFile(loc, true, expectLoc);
74 break;
75 case "output.extended":
76 expectLoc = checkFile(loc, true, expectLoc);
77 break;
78 case "options":
79 taskOptsLoc = loc;
80 Object.assign(taskOpts, require(taskOptsLoc));
81 break;
82 case "source-map":
83 sourceMapLoc = loc;
84 break;
85 case "source-map-visual":
86 sourceMapVisualLoc = loc;
87 break;
88 case "input-source-map":
89 inputSourceMap = JSON.parse(readFile(loc));
90 break;
91 }
92 }
93 if (files.length > 0 && !actualLoc && !execLoc) {
94 console.warn(`Skipped test folder with invalid layout: ${taskDir}`);
95 return;
96 }
97 (_actualLoc = actualLoc) != null ? _actualLoc : actualLoc = taskDir + "/input.js";
98 (_execLoc = execLoc) != null ? _execLoc : execLoc = taskDir + "/exec.js";
99 (_expectLoc = expectLoc) != null ? _expectLoc : expectLoc = taskDir + "/output.js";
100 stdoutLoc = taskDir + "/stdout.txt";
101 stderrLoc = taskDir + "/stderr.txt";
102 } else if (taskDirStats.isFile()) {
103 const ext = _path.extname(taskDir);
104 if (EXTENSIONS.indexOf(ext) === -1) return;
105 execLoc = taskDir;
106 execLocAlias = suiteName + "/" + taskName;
107 } else {
108 console.warn(`Skipped test folder with invalid layout: ${taskDir}`);
109 return;
110 }
111 const shouldIgnore = taskOpts.BABEL_8_BREAKING === true || taskOpts.SKIP_ON_PUBLISH;
112 if (shouldIgnore) return;
113 function buildTestFile(loc, fileName) {
114 return {
115 loc,
116 code: readFile(loc),
117 filename: !loc ? undefined : fileName === true ? suiteName + "/" + taskName + "/" + _path.basename(loc) : fileName || undefined
118 };
119 }
120 const sourceMapFile = buildTestFile(sourceMapLoc, true);
121 sourceMapFile.code && (sourceMapFile.code = JSON.parse(sourceMapFile.code));
122 const test = {
123 taskDir,
124 optionsDir: taskOptsLoc ? _path.dirname(taskOptsLoc) : null,
125 title: humanize(taskName, true),
126 disabled: taskName[0] === "." ? true : process.env.TEST_babel7plugins_babel8core && taskOpts.SKIP_babel7plugins_babel8core || false,
127 options: taskOpts,
128 doNotSetSourceType: taskOpts.DO_NOT_SET_SOURCE_TYPE,
129 externalHelpers: (_taskOpts$externalHel = taskOpts.externalHelpers) != null ? _taskOpts$externalHel : !!tryResolve("@babel/plugin-external-helpers"),
130 validateLogs: taskOpts.validateLogs,
131 ignoreOutput: taskOpts.ignoreOutput,
132 stdout: buildTestFile(stdoutLoc),
133 stderr: buildTestFile(stderrLoc),
134 exec: buildTestFile(execLoc, execLocAlias),
135 actual: buildTestFile(actualLoc, true),
136 expect: buildTestFile(expectLoc, true),
137 sourceMap: sourceMapFile.code,
138 sourceMapFile,
139 sourceMapVisual: buildTestFile(sourceMapVisualLoc),
140 validateSourceMapVisual: taskOpts.sourceMaps === true || taskOpts.sourceMaps === "both",
141 inputSourceMap
142 };
143 if (test.exec.code && test.actual.code && _path.extname(execLoc) !== _path.extname(actualLoc)) {
144 throw new Error(`Input file extension should match exec file extension: ${execLoc}, ${actualLoc}`);
145 }
146 delete taskOpts.BABEL_8_BREAKING;
147 delete taskOpts.DO_NOT_SET_SOURCE_TYPE;
148 delete taskOpts.SKIP_ON_PUBLISH;
149 delete taskOpts.SKIP_babel7plugins_babel8core;
150 if (taskOpts.minNodeVersion) {
151 const minimumVersion = _semver.clean(taskOpts.minNodeVersion);
152 if (minimumVersion == null) {
153 throw new Error(`'minNodeVersion' has invalid semver format: ${taskOpts.minNodeVersion}`);
154 }
155 if (_semver.lt(nodeVersion, minimumVersion)) {
156 if (test.actual.code) {
157 test.exec.code = null;
158 } else {
159 return;
160 }
161 }
162 delete taskOpts.minNodeVersion;
163 }
164 if (taskOpts.minNodeVersionTransform) {
165 const minimumVersion = _semver.clean(taskOpts.minNodeVersionTransform);
166 if (minimumVersion == null) {
167 throw new Error(`'minNodeVersionTransform' has invalid semver format: ${taskOpts.minNodeVersionTransform}`);
168 }
169 if (_semver.lt(nodeVersion, minimumVersion)) {
170 return;
171 }
172 delete taskOpts.minNodeVersionTransform;
173 }
174 if (taskOpts.os) {
175 let os = taskOpts.os;
176 if (!Array.isArray(os) && typeof os !== "string") {
177 throw new Error(`'os' should be either string or string array: ${taskOpts.os}`);
178 }
179 if (typeof os === "string") {
180 os = [os];
181 }
182 if (!os.includes(process.platform)) {
183 return;
184 }
185 delete taskOpts.os;
186 }
187 suite.tests.push(test);
188 if (taskOpts.throws) {
189 if (test.expect.code) {
190 throw new Error("Test cannot throw and also return output code: " + expectLoc);
191 }
192 if (test.sourceMap) {
193 throw new Error("Test cannot throw and also return sourcemaps: " + sourceMapLoc);
194 }
195 }
196 if (!test.validateLogs && (test.stdout.code || test.stderr.code)) {
197 throw new Error("stdout.txt and stderr.txt are only allowed when the 'validateLogs' option is enabled: " + (test.stdout.code ? stdoutLoc : stderrLoc));
198 }
199 if (test.ignoreOutput) {
200 if (test.expect.code) {
201 throw new Error("Test cannot ignore its output and also validate it: " + expectLoc);
202 }
203 if (!test.validateLogs) {
204 throw new Error("ignoreOutput can only be used when validateLogs is true: " + taskOptsLoc);
205 }
206 }
207 delete test.options.validateLogs;
208 delete test.options.ignoreOutput;
209 delete test.options.externalHelpers;
210}
211function wrapPackagesArray(type, names, optionsDir) {
212 return names.map(function (val) {
213 if (typeof val === "string") val = [val];
214 if (val[0][0] === ".") {
215 if (!optionsDir) {
216 throw new Error("Please provide an options.json in test dir when using a " + "relative plugin path.");
217 }
218 val[0] = _path.resolve(optionsDir, val[0]);
219 } else {
220 let name = val[0];
221 const match = name.match(/^(@babel\/(?:plugin-|preset-)?)(.*)$/);
222 if (match) {
223 name = match[2];
224 }
225 const monorepoPath = _path.join(_path.dirname(__filename), "../../..", name.startsWith("codemod") ? "codemods" : "packages", `babel-${type}-${name}/lib/index.js`);
226 if (_fs.existsSync(monorepoPath)) {
227 if (match) {
228 throw new Error(`Remove the "${match[1]}" prefix from "${val[0]}", to load it from the monorepo`);
229 }
230 val[0] = monorepoPath;
231 }
232 }
233 return val;
234 });
235}
236function resolveOptionPluginOrPreset(options, optionsDir) {
237 if (options.overrides) {
238 for (const subOption of options.overrides) {
239 resolveOptionPluginOrPreset(subOption, optionsDir);
240 }
241 }
242 if (options.env) {
243 for (const envName in options.env) {
244 if (!hasOwnProperty.call(options.env, envName)) continue;
245 resolveOptionPluginOrPreset(options.env[envName], optionsDir);
246 }
247 }
248 if (options.plugins) {
249 options.plugins = wrapPackagesArray("plugin", options.plugins, optionsDir);
250 }
251 if (options.presets) {
252 options.presets = wrapPackagesArray("preset", options.presets, optionsDir).map(function (val) {
253 if (val.length > 3) {
254 throw new Error("Unexpected extra options " + JSON.stringify(val.slice(3)) + " passed to preset.");
255 }
256 return val;
257 });
258 }
259 return options;
260}
261function get(entryLoc) {
262 const suites = [];
263 let rootOpts = {};
264 const rootOptsLoc = tryResolve(entryLoc + "/options");
265 if (rootOptsLoc) rootOpts = require(rootOptsLoc);
266 for (const suiteName of _fs.readdirSync(entryLoc)) {
267 if (shouldIgnore(suiteName)) continue;
268 const suite = {
269 options: Object.assign({}, rootOpts),
270 tests: [],
271 title: humanize(suiteName),
272 filename: entryLoc + "/" + suiteName
273 };
274 assertDirectory(suite.filename);
275 suites.push(suite);
276 const suiteOptsLoc = tryResolve(suite.filename + "/options");
277 if (suiteOptsLoc) {
278 suite.options = resolveOptionPluginOrPreset(require(suiteOptsLoc), suite.filename);
279 }
280 for (const taskName of _fs.readdirSync(suite.filename)) {
281 pushTask(taskName, suite.filename + "/" + taskName, suite, suiteName);
282 }
283 }
284 return suites;
285}
286function multiple(entryLoc, ignore) {
287 const categories = {};
288 for (const name of _fs.readdirSync(entryLoc)) {
289 if (shouldIgnore(name, ignore)) continue;
290 const loc = _path.join(entryLoc, name);
291 assertDirectory(loc);
292 categories[name] = get(loc);
293 }
294 return categories;
295}
296function readFile(filename) {
297 try {
298 if (filename === undefined) {
299 return "";
300 }
301 return _fs.readFileSync(filename, "utf8").trimRight();
302 } catch (e) {
303 if (e.code === "ENOENT") {
304 return "";
305 }
306 throw e;
307 }
308}
309
310//# sourceMappingURL=index.js.map