qunitx-cli 0.1.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +7 -0
- package/.env +1 -0
- package/Makefile +35 -0
- package/README.md +120 -49
- package/cli.js +1 -1
- package/cliff.toml +23 -0
- package/demo/demo.gif +0 -0
- package/demo/demo.tape +59 -0
- package/demo/example-test.js +53 -0
- package/demo/failing-test.js +22 -0
- package/flake.lock +4 -4
- package/flake.nix +33 -4
- package/lib/boilerplates/default-project-config-values.js +2 -2
- package/lib/boilerplates/test.js +5 -4
- package/lib/commands/generate.js +6 -8
- package/lib/commands/help.js +8 -8
- package/lib/commands/init.js +35 -25
- package/lib/commands/run/tests-in-browser.js +97 -67
- package/lib/commands/run.js +165 -55
- package/lib/servers/http.js +53 -42
- package/lib/setup/bind-server-to-port.js +3 -12
- package/lib/setup/browser.js +26 -18
- package/lib/setup/config.js +8 -10
- package/lib/setup/file-watcher.js +23 -6
- package/lib/setup/fs-tree.js +29 -27
- package/lib/setup/keyboard-events.js +7 -4
- package/lib/setup/test-file-paths.js +25 -23
- package/lib/setup/web-server.js +87 -61
- package/lib/setup/write-output-static-files.js +4 -1
- package/lib/tap/display-final-result.js +2 -2
- package/lib/tap/display-test-result.js +32 -14
- package/lib/utils/find-chrome.js +16 -0
- package/lib/utils/find-internal-assets-from-html.js +7 -5
- package/lib/utils/find-project-root.js +1 -2
- package/lib/utils/indent-string.js +6 -6
- package/lib/utils/listen-to-keyboard-key.js +6 -2
- package/lib/utils/parse-cli-flags.js +34 -31
- package/lib/utils/resolve-port-number-for.js +3 -3
- package/lib/utils/run-user-module.js +5 -3
- package/lib/utils/search-in-parent-directories.js +4 -1
- package/lib/utils/time-counter.js +2 -2
- package/package.json +21 -36
- package/vendor/qunit.css +7 -7
- package/vendor/qunit.js +3772 -3324
package/lib/servers/http.js
CHANGED
|
@@ -3,14 +3,14 @@ import WebSocket, { WebSocketServer } from 'ws';
|
|
|
3
3
|
import bindServerToPort from '../setup/bind-server-to-port.js';
|
|
4
4
|
|
|
5
5
|
export const MIME_TYPES = {
|
|
6
|
-
html:
|
|
7
|
-
js:
|
|
8
|
-
css:
|
|
9
|
-
png:
|
|
10
|
-
jpg:
|
|
11
|
-
gif:
|
|
12
|
-
ico:
|
|
13
|
-
svg:
|
|
6
|
+
html: 'text/html; charset=UTF-8',
|
|
7
|
+
js: 'application/javascript',
|
|
8
|
+
css: 'text/css',
|
|
9
|
+
png: 'image/png',
|
|
10
|
+
jpg: 'image/jpg',
|
|
11
|
+
gif: 'image/gif',
|
|
12
|
+
ico: 'image/x-icon',
|
|
13
|
+
svg: 'image/svg+xml',
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export default class HTTPServer {
|
|
@@ -23,13 +23,15 @@ export default class HTTPServer {
|
|
|
23
23
|
return handler(req, res);
|
|
24
24
|
});
|
|
25
25
|
server = server;
|
|
26
|
-
server
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
server
|
|
27
|
+
.on('error', (error) => {
|
|
28
|
+
onError(error);
|
|
29
|
+
reject(error);
|
|
30
|
+
})
|
|
31
|
+
.once('listening', () => {
|
|
32
|
+
onListen(Object.assign({ hostname: '127.0.0.1', server }, config));
|
|
33
|
+
resolve(server);
|
|
34
|
+
});
|
|
33
35
|
|
|
34
36
|
server.wss = new WebSocketServer({ server });
|
|
35
37
|
server.wss.on('error', (error) => {
|
|
@@ -37,7 +39,7 @@ export default class HTTPServer {
|
|
|
37
39
|
console.trace(error);
|
|
38
40
|
});
|
|
39
41
|
|
|
40
|
-
bindServerToPort(server, config)
|
|
42
|
+
bindServerToPort(server, config);
|
|
41
43
|
});
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -46,7 +48,7 @@ export default class HTTPServer {
|
|
|
46
48
|
GET: {},
|
|
47
49
|
POST: {},
|
|
48
50
|
DELETE: {},
|
|
49
|
-
PUT: {}
|
|
51
|
+
PUT: {},
|
|
50
52
|
};
|
|
51
53
|
this.middleware = [];
|
|
52
54
|
this._server = http.createServer((req, res) => {
|
|
@@ -78,13 +80,17 @@ export default class HTTPServer {
|
|
|
78
80
|
|
|
79
81
|
listen(port = 0, callback = () => {}) {
|
|
80
82
|
return new Promise((resolve, reject) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
const onError = (err) => {
|
|
84
|
+
this._server.off('listening', onListening);
|
|
85
|
+
reject(err);
|
|
86
|
+
};
|
|
87
|
+
const onListening = () => {
|
|
88
|
+
this._server.off('error', onError);
|
|
89
|
+
resolve(callback());
|
|
90
|
+
};
|
|
91
|
+
this._server.once('error', onError);
|
|
92
|
+
this._server.once('listening', onListening);
|
|
93
|
+
this._server.listen(port);
|
|
88
94
|
});
|
|
89
95
|
}
|
|
90
96
|
|
|
@@ -121,7 +127,7 @@ export default class HTTPServer {
|
|
|
121
127
|
path,
|
|
122
128
|
handler,
|
|
123
129
|
paramNames: this.extractParamNames(path),
|
|
124
|
-
isWildcard: path === '/*'
|
|
130
|
+
isWildcard: path === '/*',
|
|
125
131
|
};
|
|
126
132
|
}
|
|
127
133
|
|
|
@@ -159,27 +165,32 @@ export default class HTTPServer {
|
|
|
159
165
|
return null;
|
|
160
166
|
}
|
|
161
167
|
|
|
162
|
-
return
|
|
163
|
-
|
|
168
|
+
return (
|
|
169
|
+
routes[url] ||
|
|
170
|
+
Object.values(routes).find((route) => {
|
|
171
|
+
const { path, isWildcard } = route;
|
|
164
172
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
173
|
+
if (!isWildcard && !path.includes(':')) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
168
176
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
if (isWildcard || this.matchPathSegments(path, url)) {
|
|
178
|
+
if (route.paramNames.length > 0) {
|
|
179
|
+
const regexPattern = this.buildRegexPattern(path, route.paramNames);
|
|
180
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
181
|
+
const regexMatches = regex.exec(url);
|
|
182
|
+
if (regexMatches) {
|
|
183
|
+
route.paramValues = regexMatches.slice(1);
|
|
184
|
+
}
|
|
176
185
|
}
|
|
186
|
+
return true;
|
|
177
187
|
}
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
188
|
|
|
181
|
-
|
|
182
|
-
|
|
189
|
+
return false;
|
|
190
|
+
}) ||
|
|
191
|
+
routes['/*'] ||
|
|
192
|
+
null
|
|
193
|
+
);
|
|
183
194
|
}
|
|
184
195
|
|
|
185
196
|
matchPathSegments(path, url) {
|
|
@@ -217,7 +228,7 @@ export default class HTTPServer {
|
|
|
217
228
|
const paramRegex = /:(\w+)/g;
|
|
218
229
|
const paramMatches = path.match(paramRegex);
|
|
219
230
|
|
|
220
|
-
return paramMatches ? paramMatches.map(match => match.slice(1)) : [];
|
|
231
|
+
return paramMatches ? paramMatches.map((match) => match.slice(1)) : [];
|
|
221
232
|
}
|
|
222
233
|
|
|
223
234
|
extractParams(route, url) {
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import resolvePortNumberFor from '../utils/resolve-port-number-for.js';
|
|
2
|
-
|
|
3
|
-
// NOTE: there was a race condition between socket.connection and server.listen, check if nanoexpress fixes it
|
|
4
1
|
export default async function bindServerToPort(server, config) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
await server.listen(port);
|
|
9
|
-
|
|
10
|
-
return server;
|
|
11
|
-
} catch(e) {
|
|
12
|
-
return await bindServerToPort(server, Object.assign(config, { port: config.port + 1 }));
|
|
13
|
-
}
|
|
2
|
+
await server.listen(0);
|
|
3
|
+
config.port = server._server.address().port;
|
|
4
|
+
return server;
|
|
14
5
|
}
|
package/lib/setup/browser.js
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
import Puppeteer from 'puppeteer';
|
|
2
2
|
import setupWebServer from './web-server.js';
|
|
3
3
|
import bindServerToPort from './bind-server-to-port.js';
|
|
4
|
+
import findChrome from '../utils/find-chrome.js';
|
|
4
5
|
|
|
5
|
-
export default async function setupBrowser(
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export default async function setupBrowser(
|
|
7
|
+
config = {
|
|
8
|
+
port: 1234,
|
|
9
|
+
debug: false,
|
|
10
|
+
watch: false,
|
|
11
|
+
timeout: 10000,
|
|
12
|
+
},
|
|
13
|
+
cachedContent,
|
|
14
|
+
existingBrowser = null,
|
|
15
|
+
) {
|
|
8
16
|
let [server, browser] = await Promise.all([
|
|
9
17
|
setupWebServer(config, cachedContent),
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
existingBrowser
|
|
19
|
+
? Promise.resolve(existingBrowser)
|
|
20
|
+
: Puppeteer.launch({
|
|
21
|
+
debugger: config.debug || false,
|
|
22
|
+
args: [
|
|
23
|
+
'--no-sandbox',
|
|
24
|
+
'--disable-gpu',
|
|
25
|
+
'--remote-debugging-port=0',
|
|
26
|
+
'--window-size=1440,900',
|
|
27
|
+
],
|
|
28
|
+
executablePath: await findChrome(),
|
|
29
|
+
headless: true,
|
|
30
|
+
}),
|
|
20
31
|
]);
|
|
32
|
+
let [page, _] = await Promise.all([browser.newPage(), bindServerToPort(server, config)]);
|
|
21
33
|
|
|
22
34
|
page.on('console', async (msg) => {
|
|
23
35
|
if (config.debug) {
|
|
@@ -28,7 +40,7 @@ export default async function setupBrowser(config = {
|
|
|
28
40
|
});
|
|
29
41
|
page.on('error', (msg) => {
|
|
30
42
|
try {
|
|
31
|
-
throw
|
|
43
|
+
throw msg;
|
|
32
44
|
} catch (e) {
|
|
33
45
|
console.error(e, e.stack);
|
|
34
46
|
console.log(e, e.stack);
|
|
@@ -49,7 +61,3 @@ export default async function setupBrowser(config = {
|
|
|
49
61
|
function turnToObjects(jsHandle) {
|
|
50
62
|
return jsHandle.jsonValue();
|
|
51
63
|
}
|
|
52
|
-
|
|
53
|
-
// function turnMStoSecond(timeInMS) {
|
|
54
|
-
// return (timeInMS / 1000).toFixed(2);
|
|
55
|
-
// }
|
package/lib/setup/config.js
CHANGED
|
@@ -7,23 +7,21 @@ import parseCliFlags from '../utils/parse-cli-flags.js';
|
|
|
7
7
|
|
|
8
8
|
export default async function setupConfig() {
|
|
9
9
|
let projectRoot = await findProjectRoot();
|
|
10
|
-
let
|
|
11
|
-
|
|
12
|
-
parseCliFlags(projectRoot)
|
|
13
|
-
]);
|
|
10
|
+
let cliConfigFlags = parseCliFlags(projectRoot);
|
|
11
|
+
let projectPackageJSON = await readConfigFromPackageJSON(projectRoot);
|
|
14
12
|
let inputs = cliConfigFlags.inputs.concat(readInputsFromPackageJSON(projectPackageJSON));
|
|
15
13
|
let config = {
|
|
16
|
-
projectRoot,
|
|
17
|
-
htmlPaths: [],
|
|
18
|
-
lastFailedTestFiles: null,
|
|
19
|
-
lastRanTestFiles: null,
|
|
20
14
|
...defaultProjectConfigValues,
|
|
15
|
+
htmlPaths: [],
|
|
21
16
|
...projectPackageJSON.qunitx,
|
|
22
17
|
...cliConfigFlags,
|
|
23
|
-
|
|
18
|
+
projectRoot,
|
|
19
|
+
inputs,
|
|
20
|
+
testFileLookupPaths: setupTestFilePaths(projectRoot, inputs),
|
|
21
|
+
lastFailedTestFiles: null,
|
|
22
|
+
lastRanTestFiles: null,
|
|
24
23
|
};
|
|
25
24
|
config.htmlPaths = normalizeHTMLPaths(config.projectRoot, config.htmlPaths);
|
|
26
|
-
config.testFileLookupPaths = setupTestFilePaths(config.projectRoot, config.inputs);
|
|
27
25
|
config.fsTree = await setupFSTree(config.testFileLookupPaths, config);
|
|
28
26
|
|
|
29
27
|
return config;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import chokidar from 'chokidar';
|
|
2
2
|
import kleur from 'kleur';
|
|
3
3
|
|
|
4
|
-
export default async function setupFileWatchers(
|
|
4
|
+
export default async function setupFileWatchers(
|
|
5
|
+
testFileLookupPaths,
|
|
6
|
+
config,
|
|
7
|
+
onEventFunc,
|
|
8
|
+
onFinishFunc,
|
|
9
|
+
) {
|
|
5
10
|
let extensions = ['js', 'ts'];
|
|
6
11
|
let fileWatchers = testFileLookupPaths.reduce((watcher, watchPath) => {
|
|
7
12
|
return Object.assign(watcher, {
|
|
@@ -9,14 +14,26 @@ export default async function setupFileWatchers(testFileLookupPaths, config, onE
|
|
|
9
14
|
if (extensions.some((extension) => path.endsWith(extension))) {
|
|
10
15
|
mutateFSTree(config.fsTree, event, path);
|
|
11
16
|
|
|
12
|
-
console.log(
|
|
17
|
+
console.log(
|
|
18
|
+
'#',
|
|
19
|
+
kleur
|
|
20
|
+
.magenta()
|
|
21
|
+
.bold('=================================================================='),
|
|
22
|
+
);
|
|
13
23
|
console.log('#', getEventColor(event), path.split(config.projectRoot)[1]);
|
|
14
|
-
console.log(
|
|
24
|
+
console.log(
|
|
25
|
+
'#',
|
|
26
|
+
kleur
|
|
27
|
+
.magenta()
|
|
28
|
+
.bold('=================================================================='),
|
|
29
|
+
);
|
|
15
30
|
|
|
16
31
|
if (!global.chokidarBuild) {
|
|
17
32
|
global.chokidarBuild = true;
|
|
18
33
|
|
|
19
|
-
let result = extensions.some((extension) => path.endsWith(extension))
|
|
34
|
+
let result = extensions.some((extension) => path.endsWith(extension))
|
|
35
|
+
? onEventFunc(event, path)
|
|
36
|
+
: null;
|
|
20
37
|
|
|
21
38
|
if (!(result instanceof Promise)) {
|
|
22
39
|
global.chokidarBuild = false;
|
|
@@ -35,7 +52,7 @@ export default async function setupFileWatchers(testFileLookupPaths, config, onE
|
|
|
35
52
|
.finally(() => (global.chokidarBuild = false));
|
|
36
53
|
}
|
|
37
54
|
}
|
|
38
|
-
})
|
|
55
|
+
}),
|
|
39
56
|
});
|
|
40
57
|
}, {});
|
|
41
58
|
|
|
@@ -45,7 +62,7 @@ export default async function setupFileWatchers(testFileLookupPaths, config, onE
|
|
|
45
62
|
Object.keys(fileWatchers).forEach((watcherKey) => fileWatchers[watcherKey].close());
|
|
46
63
|
|
|
47
64
|
return fileWatchers;
|
|
48
|
-
}
|
|
65
|
+
},
|
|
49
66
|
};
|
|
50
67
|
}
|
|
51
68
|
|
package/lib/setup/fs-tree.js
CHANGED
|
@@ -6,43 +6,45 @@ export default async function buildFSTree(fileAbsolutePaths, config = {}) {
|
|
|
6
6
|
let targetExtensions = ['js', 'ts'];
|
|
7
7
|
let fsTree = {};
|
|
8
8
|
|
|
9
|
-
await Promise.all(
|
|
10
|
-
|
|
9
|
+
await Promise.all(
|
|
10
|
+
fileAbsolutePaths.map(async (fileAbsolutePath) => {
|
|
11
|
+
let glob = picomatch.scan(fileAbsolutePath);
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
// TODO: maybe allow absolute path references
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let fileNames = await recursiveLookup(glob.base, (path) => {
|
|
17
|
-
return targetExtensions.some((extension) => path.endsWith(extension));
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
fileNames.forEach((fileName) => {
|
|
21
|
-
if (picomatch.isMatch(fileName, fileAbsolutePath, { bash: true })) {
|
|
22
|
-
fsTree[fileName] = null;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
} else {
|
|
26
|
-
let entry = await fs.stat(fileAbsolutePath);
|
|
27
|
-
|
|
28
|
-
if (entry.isFile()) {
|
|
29
|
-
fsTree[fileAbsolutePath] = null;
|
|
30
|
-
} else if (entry.isDirectory()) {
|
|
15
|
+
try {
|
|
16
|
+
if (glob.isGlob) {
|
|
31
17
|
let fileNames = await recursiveLookup(glob.base, (path) => {
|
|
32
18
|
return targetExtensions.some((extension) => path.endsWith(extension));
|
|
33
19
|
});
|
|
34
20
|
|
|
35
21
|
fileNames.forEach((fileName) => {
|
|
36
|
-
|
|
22
|
+
if (picomatch.isMatch(fileName, fileAbsolutePath, { bash: true })) {
|
|
23
|
+
fsTree[fileName] = null;
|
|
24
|
+
}
|
|
37
25
|
});
|
|
26
|
+
} else {
|
|
27
|
+
let entry = await fs.stat(fileAbsolutePath);
|
|
28
|
+
|
|
29
|
+
if (entry.isFile()) {
|
|
30
|
+
fsTree[fileAbsolutePath] = null;
|
|
31
|
+
} else if (entry.isDirectory()) {
|
|
32
|
+
let fileNames = await recursiveLookup(glob.base, (path) => {
|
|
33
|
+
return targetExtensions.some((extension) => path.endsWith(extension));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
fileNames.forEach((fileName) => {
|
|
37
|
+
fsTree[fileName] = null;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
38
40
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
console.error(error);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error(error);
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
return process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
46
48
|
|
|
47
49
|
return fsTree;
|
|
48
50
|
}
|
|
@@ -6,21 +6,24 @@ export default function setupKeyboardEvents(config, cachedContent, connections)
|
|
|
6
6
|
listenToKeyboardKey('qq', () => abortBrowserQUnit(config, connections));
|
|
7
7
|
listenToKeyboardKey('qa', () => {
|
|
8
8
|
abortBrowserQUnit(config, connections);
|
|
9
|
-
runTestsInBrowser(config, cachedContent, connections)
|
|
9
|
+
runTestsInBrowser(config, cachedContent, connections);
|
|
10
10
|
});
|
|
11
11
|
listenToKeyboardKey('qf', () => {
|
|
12
12
|
abortBrowserQUnit(config, connections);
|
|
13
13
|
|
|
14
14
|
if (!config.lastFailedTestFiles) {
|
|
15
|
-
console.log(
|
|
15
|
+
console.log(
|
|
16
|
+
'#',
|
|
17
|
+
kleur.blue(`QUnitX: No tests failed so far, so repeating the last test run`),
|
|
18
|
+
);
|
|
16
19
|
return runTestsInBrowser(config, cachedContent, connections, config.lastRanTestFiles);
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
runTestsInBrowser(config, cachedContent, connections, config.lastFailedTestFiles)
|
|
22
|
+
runTestsInBrowser(config, cachedContent, connections, config.lastFailedTestFiles);
|
|
20
23
|
});
|
|
21
24
|
listenToKeyboardKey('ql', () => {
|
|
22
25
|
abortBrowserQUnit(config, connections);
|
|
23
|
-
runTestsInBrowser(config, cachedContent, connections, config.lastRanTestFiles)
|
|
26
|
+
runTestsInBrowser(config, cachedContent, connections, config.lastRanTestFiles);
|
|
24
27
|
});
|
|
25
28
|
}
|
|
26
29
|
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import picomatch from 'picomatch';
|
|
2
2
|
|
|
3
|
-
export default function setupTestFilePaths(projectRoot, inputs) {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export default function setupTestFilePaths(projectRoot, inputs) {
|
|
4
|
+
// NOTE: very complex algorithm, order is very important
|
|
5
|
+
let [folders, filesWithGlob, filesWithoutGlob] = inputs.reduce(
|
|
6
|
+
(result, input) => {
|
|
7
|
+
let isGlob = picomatch.scan(input).isGlob;
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
if (!pathIsFile(input)) {
|
|
10
|
+
result[0].push({
|
|
11
|
+
input,
|
|
12
|
+
isFile: false,
|
|
13
|
+
isGlob,
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
result[isGlob ? 1 : 2].push({
|
|
17
|
+
input,
|
|
18
|
+
isFile: true,
|
|
19
|
+
isGlob,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
return result;
|
|
24
|
+
},
|
|
25
|
+
[[], [], []],
|
|
26
|
+
);
|
|
23
27
|
|
|
24
28
|
let result = folders.reduce((folderResult, folder) => {
|
|
25
29
|
if (!pathIsIncludedInPaths(folders, folder)) {
|
|
@@ -30,10 +34,7 @@ export default function setupTestFilePaths(projectRoot, inputs) { // NOTE: very
|
|
|
30
34
|
}, []);
|
|
31
35
|
|
|
32
36
|
filesWithGlob.forEach((file) => {
|
|
33
|
-
if (
|
|
34
|
-
!pathIsIncludedInPaths(result, file) &&
|
|
35
|
-
!pathIsIncludedInPaths(filesWithGlob, file)
|
|
36
|
-
) {
|
|
37
|
+
if (!pathIsIncludedInPaths(result, file) && !pathIsIncludedInPaths(filesWithGlob, file)) {
|
|
37
38
|
result.push(file);
|
|
38
39
|
}
|
|
39
40
|
});
|
|
@@ -68,7 +69,8 @@ function buildGlobFormat(path) {
|
|
|
68
69
|
if (!path.isFile) {
|
|
69
70
|
if (!path.isGlob) {
|
|
70
71
|
return `${path.input}/*`;
|
|
71
|
-
} else if (path.input.endsWith('*')) {
|
|
72
|
+
} else if (path.input.endsWith('*')) {
|
|
73
|
+
// NOTE: could be problematic in future, investigate if I should check endsWith /*
|
|
72
74
|
return path.input;
|
|
73
75
|
}
|
|
74
76
|
|