@brillout/test-e2e 0.5.28 → 0.5.30
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/dist/Logs/isTolerateError.d.ts +2 -2
- package/dist/Logs/isTolerateError.js +5 -11
- package/dist/Logs.d.ts +2 -2
- package/dist/Logs.js +26 -32
- package/dist/TIMEOUTS.js +6 -9
- package/dist/autoRetry.js +5 -8
- package/dist/buildTs.js +10 -16
- package/dist/chai/JestChaiExpect.d.ts +1 -1
- package/dist/chai/JestChaiExpect.js +1 -5
- package/dist/chai/expect.d.ts +1 -1
- package/dist/chai/expect.js +4 -30
- package/dist/chai/types.d.ts +4 -4
- package/dist/chai/types.js +1 -2
- package/dist/cli.js +13 -18
- package/dist/editFile.js +15 -21
- package/dist/fetch.d.ts +2 -2
- package/dist/fetch.js +20 -16
- package/dist/findTestFiles.d.ts +1 -1
- package/dist/findTestFiles.js +6 -9
- package/dist/getBrowser.js +9 -12
- package/dist/getConfig.d.ts +1 -1
- package/dist/getConfig.js +14 -20
- package/dist/getCurrentTest.d.ts +1 -1
- package/dist/getCurrentTest.js +15 -21
- package/dist/index.d.ts +13 -13
- package/dist/index.js +14 -38
- package/dist/logError.js +3 -6
- package/dist/logSection.js +5 -11
- package/dist/logTestStatus.js +19 -25
- package/dist/page.js +3 -6
- package/dist/parallel-ci.js +8 -14
- package/dist/run.js +42 -45
- package/dist/runAll.d.ts +1 -1
- package/dist/runAll.js +61 -67
- package/dist/runCommandThatTerminates.js +6 -9
- package/dist/skip.js +3 -6
- package/dist/test.js +5 -8
- package/dist/testScreenshotFixture.js +58 -42
- package/dist/utils/assert.js +23 -26
- package/dist/utils/cliOptions.js +9 -12
- package/dist/utils/findFiles.d.ts +1 -1
- package/dist/utils/findFiles.js +13 -19
- package/dist/utils/fsWindowsBugWorkaround.js +2 -5
- package/dist/utils/genPromise.js +1 -5
- package/dist/utils/hasProp.d.ts +15 -0
- package/dist/utils/hasProp.js +50 -0
- package/dist/utils/humanizeTime.js +1 -4
- package/dist/utils/isArray.d.ts +1 -0
- package/dist/utils/isArray.js +4 -0
- package/dist/utils/isArrayOfStrings.d.ts +2 -0
- package/dist/utils/isArrayOfStrings.js +5 -0
- package/dist/utils/isCallable.js +1 -5
- package/dist/utils/isMinNodeVersion.js +4 -7
- package/dist/utils/isObject.d.ts +1 -1
- package/dist/utils/isObject.js +1 -5
- package/dist/utils/isObjectOfStrings.d.ts +2 -0
- package/dist/utils/isObjectOfStrings.js +5 -0
- package/dist/utils/isTTY.js +1 -4
- package/dist/utils/logProgress.js +4 -7
- package/dist/utils/parseCli.js +3 -6
- package/dist/utils/platform.js +6 -9
- package/dist/utils/projectInfo.js +1 -4
- package/dist/utils/runCommand.js +7 -10
- package/dist/utils/runCommandLongRunning.js +40 -32
- package/dist/utils/runCommandShortLived.js +7 -10
- package/dist/utils/sleep.js +1 -4
- package/dist/utils/trackLogs.d.ts +1 -1
- package/dist/utils/trackLogs.js +1 -1
- package/dist/utils.d.ts +16 -0
- package/dist/utils.js +16 -0
- package/package.json +17 -4
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/index.js +0 -31
package/dist/utils/findFiles.js
CHANGED
|
@@ -1,35 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const runCommandShortLived_1 = require("./runCommandShortLived");
|
|
1
|
+
export { findFiles };
|
|
2
|
+
export { findFilesParseCliArgs };
|
|
3
|
+
export { filterFiles };
|
|
4
|
+
import glob from 'fast-glob';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { runCommandShortLived } from './runCommandShortLived.js';
|
|
10
7
|
const cwd = process.cwd();
|
|
11
8
|
let gitFiles;
|
|
12
9
|
async function findFiles(pattern) {
|
|
13
|
-
let files = (await (
|
|
10
|
+
let files = (await glob([pattern], { ignore: ['**/node_modules/**', '**/.git/**'], cwd, dot: true })).map((filePathRelative) => path.join(cwd, filePathRelative));
|
|
14
11
|
files = await filterGitIgnoredFiles(files);
|
|
15
12
|
return files;
|
|
16
13
|
}
|
|
17
|
-
exports.findFiles = findFiles;
|
|
18
14
|
function filterFiles(files, findFilter) {
|
|
19
15
|
return files
|
|
20
|
-
.map((p) =>
|
|
16
|
+
.map((p) => path.relative(cwd, p))
|
|
21
17
|
.filter((filePathRelative) => applyFilter(filePathRelative, findFilter))
|
|
22
|
-
.map((p) =>
|
|
18
|
+
.map((p) => path.join(cwd, p));
|
|
23
19
|
}
|
|
24
|
-
exports.filterFiles = filterFiles;
|
|
25
20
|
async function filterGitIgnoredFiles(files) {
|
|
26
21
|
if (!gitFiles) {
|
|
27
|
-
const stdout1 = await
|
|
22
|
+
const stdout1 = await runCommandShortLived('git ls-files', { cwd });
|
|
28
23
|
// Also include untracked files.
|
|
29
24
|
// - In other words, we remove git ignored files. (Staged files are tracked and listed by `$ git ls-files`.)
|
|
30
25
|
// - `git ls-files --others --exclude-standard` from https://stackoverflow.com/questions/3801321/git-list-only-untracked-files-also-custom-commands/3801554#3801554
|
|
31
|
-
const stdout2 = await
|
|
32
|
-
gitFiles = [...stdout1.split('\n'), ...stdout2.split('\n')].map((filePathRelative) =>
|
|
26
|
+
const stdout2 = await runCommandShortLived('git ls-files --others --exclude-standard', { cwd });
|
|
27
|
+
gitFiles = [...stdout1.split('\n'), ...stdout2.split('\n')].map((filePathRelative) => path.join(cwd, filePathRelative));
|
|
33
28
|
}
|
|
34
29
|
const filesFiltered = files.filter((file) => gitFiles.includes(file));
|
|
35
30
|
return filesFiltered;
|
|
@@ -55,7 +50,7 @@ function matches(str, chunk) {
|
|
|
55
50
|
return str.includes(chunk);
|
|
56
51
|
}
|
|
57
52
|
function normalize(p) {
|
|
58
|
-
return
|
|
53
|
+
return path.normalize(p);
|
|
59
54
|
}
|
|
60
55
|
function findFilesParseCliArgs() {
|
|
61
56
|
const terms = [];
|
|
@@ -76,4 +71,3 @@ function findFilesParseCliArgs() {
|
|
|
76
71
|
};
|
|
77
72
|
return filter;
|
|
78
73
|
}
|
|
79
|
-
exports.findFilesParseCliArgs = findFilesParseCliArgs;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.fsWindowsBugWorkaroundPrefix = exports.fsWindowsBugWorkaround = void 0;
|
|
1
|
+
export { fsWindowsBugWorkaround };
|
|
2
|
+
export { fsWindowsBugWorkaroundPrefix };
|
|
4
3
|
const fsWindowsBugWorkaroundPrefix = 'file://';
|
|
5
|
-
exports.fsWindowsBugWorkaroundPrefix = fsWindowsBugWorkaroundPrefix;
|
|
6
4
|
// https://stackoverflow.com/questions/69665780/error-err-unsupported-esm-url-scheme-only-file-and-data-urls-are-supported-by/70057245#70057245
|
|
7
5
|
function fsWindowsBugWorkaround(testFileJs) {
|
|
8
6
|
return `${fsWindowsBugWorkaroundPrefix}${testFileJs}`;
|
|
9
7
|
}
|
|
10
|
-
exports.fsWindowsBugWorkaround = fsWindowsBugWorkaround;
|
package/dist/utils/genPromise.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.genPromise = void 0;
|
|
4
|
-
function genPromise() {
|
|
1
|
+
export function genPromise() {
|
|
5
2
|
let resolve;
|
|
6
3
|
let reject;
|
|
7
4
|
const promise = new Promise((resolve_, reject_) => {
|
|
@@ -10,4 +7,3 @@ function genPromise() {
|
|
|
10
7
|
});
|
|
11
8
|
return { promise, resolve, reject };
|
|
12
9
|
}
|
|
13
|
-
exports.genPromise = genPromise;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { hasProp };
|
|
2
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'boolean'): obj is ObjectType & Record<PropName, boolean>;
|
|
3
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'number'): obj is ObjectType & Record<PropName, number>;
|
|
4
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'string'): obj is ObjectType & Record<PropName, string>;
|
|
5
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'object'): obj is ObjectType & Record<PropName, Record<string, unknown>>;
|
|
6
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'array'): obj is ObjectType & Record<PropName, unknown[]>;
|
|
7
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'string[]'): obj is ObjectType & Record<PropName, string[]>;
|
|
8
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'string{}'): obj is ObjectType & Record<PropName, Record<string, string>>;
|
|
9
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'function'): obj is ObjectType & Record<PropName, (...args: any[]) => unknown>;
|
|
10
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'undefined'): obj is ObjectType & Record<PropName, undefined>;
|
|
11
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'null'): obj is ObjectType & Record<PropName, null>;
|
|
12
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'true'): obj is ObjectType & Record<PropName, true>;
|
|
13
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName, type: 'false'): obj is ObjectType & Record<PropName, false>;
|
|
14
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey, Enum>(obj: ObjectType, prop: PropName, type: Enum[]): obj is ObjectType & Record<PropName, Enum>;
|
|
15
|
+
declare function hasProp<ObjectType, PropName extends PropertyKey>(obj: ObjectType, prop: PropName): obj is ObjectType & Record<PropName, unknown>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export { hasProp };
|
|
2
|
+
// - https://2ality.com/2020/06/type-guards-assertion-functions-typescript.html
|
|
3
|
+
// - https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABDAzgFQJ4AcCmdgAUAbgIYA2IOAXIiWBgDSJTbWIDkARnHGTnewCUNUhRzIUibr35gA3AFgAUKEiwEEzLnzFylGnUbNWNdmBABbTjgBOQkXvGpE5q7cUrw0eElRa8hKL6tPRMLLimKFA2MGAA5vaIQU6SUTHxHqreGn6sOskGocYRHOAA1mBwAO5gickSiOWVNZle6r7oeYGOhUbhbGmxcYgAvKVgFdW1wlI8fHSIAN7KiMiExeIjW+OTNeyIgksrq4g2OFAgNkjRlMcAvsdnF1cb+EmOo9v9Hg9KyhAIKK0GhNKajRAAFgATMplCQUChbFACLltIQSEwzJZrHZBIJ-oCZAA6MhwOIEEj4v6eNQ+WgIpEEAFgAAmMHaIImzTAM3hiJsUEkzLZ7SOShOa0QTIQIp8hyelzAx1WUAAFjZqi4cFVEABRGwamwEdgAQQZArpADESDAyEJlHcgA
|
|
4
|
+
import { isCallable } from './isCallable.js';
|
|
5
|
+
import { isObject } from './isObject.js';
|
|
6
|
+
import { isArrayOfStrings } from './isArrayOfStrings.js';
|
|
7
|
+
import { isObjectOfStrings } from './isObjectOfStrings.js';
|
|
8
|
+
import { isArray } from './isArray.js';
|
|
9
|
+
function hasProp(obj, prop, type = 'unknown') {
|
|
10
|
+
if (!isObject(obj))
|
|
11
|
+
return false;
|
|
12
|
+
if (!(prop in obj)) {
|
|
13
|
+
return type === 'undefined';
|
|
14
|
+
}
|
|
15
|
+
if (type === 'unknown') {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
const propValue = obj[prop];
|
|
19
|
+
if (type === 'array') {
|
|
20
|
+
return isArray(propValue);
|
|
21
|
+
}
|
|
22
|
+
if (type === 'object') {
|
|
23
|
+
return isObject(propValue);
|
|
24
|
+
}
|
|
25
|
+
if (type === 'string[]') {
|
|
26
|
+
return isArrayOfStrings(propValue);
|
|
27
|
+
}
|
|
28
|
+
if (type === 'string{}') {
|
|
29
|
+
return isObjectOfStrings(propValue);
|
|
30
|
+
}
|
|
31
|
+
if (type === 'function') {
|
|
32
|
+
return isCallable(propValue);
|
|
33
|
+
}
|
|
34
|
+
if (isArray(type)) {
|
|
35
|
+
return typeof propValue === 'string' && type.includes(propValue);
|
|
36
|
+
}
|
|
37
|
+
if (type === 'null') {
|
|
38
|
+
return propValue === null;
|
|
39
|
+
}
|
|
40
|
+
if (type === 'undefined') {
|
|
41
|
+
return propValue === undefined;
|
|
42
|
+
}
|
|
43
|
+
if (type === 'true') {
|
|
44
|
+
return propValue === true;
|
|
45
|
+
}
|
|
46
|
+
if (type === 'false') {
|
|
47
|
+
return propValue === false;
|
|
48
|
+
}
|
|
49
|
+
return typeof propValue === type;
|
|
50
|
+
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.humanizeTime = void 0;
|
|
1
|
+
export { humanizeTime };
|
|
4
2
|
function humanizeTime(milliseconds) {
|
|
5
3
|
const seconds = milliseconds / 1000;
|
|
6
4
|
if (seconds < 120) {
|
|
@@ -9,7 +7,6 @@ function humanizeTime(milliseconds) {
|
|
|
9
7
|
const minutes = seconds / 60;
|
|
10
8
|
return `${round(minutes)} minutes`;
|
|
11
9
|
}
|
|
12
|
-
exports.humanizeTime = humanizeTime;
|
|
13
10
|
function round(n) {
|
|
14
11
|
let rounded = n.toFixed(1);
|
|
15
12
|
if (rounded.endsWith('.0'))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isArray(value: unknown): value is unknown[];
|
package/dist/utils/isCallable.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isCallable = void 0;
|
|
4
|
-
function isCallable(thing) {
|
|
1
|
+
export function isCallable(thing) {
|
|
5
2
|
return thing instanceof Function || typeof thing === 'function';
|
|
6
3
|
}
|
|
7
|
-
exports.isCallable = isCallable;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.isMinNodeVersion = void 0;
|
|
4
|
-
const assert_1 = require("./assert");
|
|
1
|
+
export { isMinNodeVersion };
|
|
2
|
+
import { assert } from './assert.js';
|
|
5
3
|
function isMinNodeVersion(minNodeVersion) {
|
|
6
4
|
const { version } = process;
|
|
7
|
-
|
|
5
|
+
assert(version.startsWith('v'));
|
|
8
6
|
const major = parseInt(version[1] + version[2], 10);
|
|
9
|
-
|
|
7
|
+
assert(12 <= major && major <= 50);
|
|
10
8
|
return major >= minNodeVersion;
|
|
11
9
|
}
|
|
12
|
-
exports.isMinNodeVersion = isMinNodeVersion;
|
package/dist/utils/isObject.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function isObject(value: unknown): value is Record<string
|
|
1
|
+
export declare function isObject(value: unknown): value is Record<string, unknown>;
|
package/dist/utils/isObject.js
CHANGED
package/dist/utils/isTTY.js
CHANGED
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isTTY = void 0;
|
|
4
1
|
// https://stackoverflow.com/questions/34570452/node-js-stdout-clearline-and-cursorto-functions#comment80319576_34570694
|
|
5
|
-
|
|
2
|
+
export const isTTY = !!process.stdout.clearLine;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const isTTY_1 = require("./isTTY");
|
|
1
|
+
export { logProgress };
|
|
2
|
+
export { ensureNewTerminalLine };
|
|
3
|
+
import { isTTY } from './isTTY.js';
|
|
5
4
|
const iconSuccess = '🟢';
|
|
6
5
|
const iconPending = '🟠';
|
|
7
6
|
const iconFail = '🔴';
|
|
8
7
|
let terminalLineIsEmtpy = true;
|
|
9
8
|
function logProgress(text) {
|
|
10
|
-
if (!
|
|
9
|
+
if (!isTTY) {
|
|
11
10
|
const done = () => { };
|
|
12
11
|
return done;
|
|
13
12
|
}
|
|
@@ -25,13 +24,11 @@ function logProgress(text) {
|
|
|
25
24
|
};
|
|
26
25
|
return done;
|
|
27
26
|
}
|
|
28
|
-
exports.logProgress = logProgress;
|
|
29
27
|
function ensureNewTerminalLine() {
|
|
30
28
|
const val = terminalLineIsEmtpy;
|
|
31
29
|
terminalLineIsEmtpy = true;
|
|
32
30
|
return val;
|
|
33
31
|
}
|
|
34
|
-
exports.ensureNewTerminalLine = ensureNewTerminalLine;
|
|
35
32
|
function clear() {
|
|
36
33
|
// @ts-ignore
|
|
37
34
|
process.stdout.clearLine();
|
package/dist/utils/parseCli.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export { prepare };
|
|
2
|
+
export { check };
|
|
3
|
+
export { validate };
|
|
4
4
|
let optionList;
|
|
5
5
|
const optionsKnown = [];
|
|
6
6
|
function prepare() {
|
|
7
7
|
optionList = process.argv.filter((w) => w.startsWith('--'));
|
|
8
8
|
}
|
|
9
|
-
exports.prepare = prepare;
|
|
10
9
|
function check(option) {
|
|
11
10
|
optionsKnown.push(option);
|
|
12
11
|
const val = optionList.includes(option);
|
|
@@ -14,7 +13,6 @@ function check(option) {
|
|
|
14
13
|
optionList = optionList.filter((s) => s !== option);
|
|
15
14
|
return val;
|
|
16
15
|
}
|
|
17
|
-
exports.check = check;
|
|
18
16
|
function validate() {
|
|
19
17
|
if (optionList.length > 0) {
|
|
20
18
|
throw new Error([
|
|
@@ -24,4 +22,3 @@ function validate() {
|
|
|
24
22
|
].join('\n'));
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
|
-
exports.validate = validate;
|
package/dist/utils/platform.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export { isCI };
|
|
2
|
+
export { isLinux };
|
|
3
|
+
export { isWindows };
|
|
4
|
+
export { isMac };
|
|
5
|
+
import { assert } from './assert.js';
|
|
5
6
|
function isWindows() {
|
|
6
7
|
return process.platform === 'win32';
|
|
7
8
|
}
|
|
8
|
-
exports.isWindows = isWindows;
|
|
9
9
|
function isLinux() {
|
|
10
10
|
return process.platform === 'linux';
|
|
11
11
|
}
|
|
12
|
-
exports.isLinux = isLinux;
|
|
13
12
|
function isMac() {
|
|
14
13
|
if (process.platform === 'darwin') {
|
|
15
14
|
return true;
|
|
16
15
|
}
|
|
17
|
-
|
|
16
|
+
assert(isLinux() || isWindows());
|
|
18
17
|
return false;
|
|
19
18
|
}
|
|
20
|
-
exports.isMac = isMac;
|
|
21
19
|
function isCI() {
|
|
22
20
|
return !!process.env.CI;
|
|
23
21
|
}
|
|
24
|
-
exports.isCI = isCI;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.projectInfo = void 0;
|
|
4
|
-
exports.projectInfo = {
|
|
1
|
+
export const projectInfo = {
|
|
5
2
|
projectName: '@brillout/test-e2e',
|
|
6
3
|
npmPackageName: '@brillout/test-e2e',
|
|
7
4
|
githubRepository: 'https://github.com/brillout/test-e2e',
|
package/dist/utils/runCommand.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const genPromise_1 = require("./genPromise");
|
|
6
|
-
const humanizeTime_1 = require("./humanizeTime");
|
|
1
|
+
export { runCommand };
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import { genPromise } from './genPromise.js';
|
|
4
|
+
import { humanizeTime } from './humanizeTime.js';
|
|
7
5
|
function runCommand(cmd, { timeout, cwd }) {
|
|
8
|
-
const { promise, resolve, reject } =
|
|
6
|
+
const { promise, resolve, reject } = genPromise();
|
|
9
7
|
const t = setTimeout(() => {
|
|
10
|
-
reject(new Error(`Command call \`${cmd}\` (${cwd}) timed out after ${
|
|
8
|
+
reject(new Error(`Command call \`${cmd}\` (${cwd}) timed out after ${humanizeTime(timeout)}`));
|
|
11
9
|
}, timeout);
|
|
12
|
-
|
|
10
|
+
exec(cmd, { cwd }, (err, _stdout, stderr) => {
|
|
13
11
|
clearTimeout(t);
|
|
14
12
|
if (stderr) {
|
|
15
13
|
reject(new Error(stderr));
|
|
@@ -23,4 +21,3 @@ function runCommand(cmd, { timeout, cwd }) {
|
|
|
23
21
|
});
|
|
24
22
|
return promise;
|
|
25
23
|
}
|
|
26
|
-
exports.runCommand = runCommand;
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.runCommandLongRunning = void 0;
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const strip_ansi_1 = __importDefault(require("strip-ansi"));
|
|
9
|
-
const utils_1 = require("../utils");
|
|
1
|
+
export { runCommandLongRunning };
|
|
2
|
+
import { spawn as spawn_ } from 'child_process';
|
|
3
|
+
import stripAnsi from 'strip-ansi';
|
|
4
|
+
import { assert, runCommandShortLived, humanizeTime, isWindows, isLinux, isCallable, hasProp } from '../utils.js';
|
|
10
5
|
function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout, onStdout, onStderr, onExit, onTerminationError, terminationTimeout, }) {
|
|
11
6
|
if (killPort)
|
|
12
7
|
killByPort(killPort);
|
|
@@ -16,7 +11,7 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
16
11
|
const isReadyPromise = new Promise((resolve_, reject_) => {
|
|
17
12
|
onReady = () => {
|
|
18
13
|
clearTimeout(isReadyPromiseTimeout);
|
|
19
|
-
|
|
14
|
+
assert(!procExited);
|
|
20
15
|
isReady = true;
|
|
21
16
|
resolve_();
|
|
22
17
|
};
|
|
@@ -25,16 +20,16 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
25
20
|
// We reject before terminating the process in order to preserve log order. (This order is fine because the test runner doesn't exit upon test failure.)
|
|
26
21
|
reject_(err);
|
|
27
22
|
if (!alreadyTerminated) {
|
|
28
|
-
|
|
23
|
+
assert(!procExited);
|
|
29
24
|
await terminateProc(true);
|
|
30
25
|
}
|
|
31
|
-
|
|
26
|
+
assert(procExited);
|
|
32
27
|
};
|
|
33
28
|
});
|
|
34
29
|
let isReadyPromiseTimedOut = false;
|
|
35
30
|
const isReadyPromiseTimeout = setTimeout(async () => {
|
|
36
31
|
isReadyPromiseTimedOut = true;
|
|
37
|
-
let errMsg = `Command \`${cmd}\` not ready after ${
|
|
32
|
+
let errMsg = `Command \`${cmd}\` not ready after ${humanizeTime(isReadyTimeout)}.`;
|
|
38
33
|
if (typeof isReadyLog === 'string') {
|
|
39
34
|
errMsg += ` The stdout of the command did not (yet?) include "${isReadyLog}".`;
|
|
40
35
|
}
|
|
@@ -42,13 +37,13 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
42
37
|
}, isReadyTimeout);
|
|
43
38
|
let [command, ...args] = cmd.split(' ');
|
|
44
39
|
let detached = true;
|
|
45
|
-
if (
|
|
40
|
+
if (isWindows()) {
|
|
46
41
|
detached = false;
|
|
47
42
|
if (command === 'npm' || command === 'pnpm') {
|
|
48
43
|
command = command + '.cmd';
|
|
49
44
|
}
|
|
50
45
|
}
|
|
51
|
-
const proc =
|
|
46
|
+
const proc = spawn(command, args, { cwd, detached });
|
|
52
47
|
let procExited = false;
|
|
53
48
|
proc.stdin.on('data', async (chunk) => {
|
|
54
49
|
const data = String(chunk);
|
|
@@ -58,16 +53,16 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
58
53
|
const log = String(chunk);
|
|
59
54
|
onStdout(log, { loggedAfterExit: procExited });
|
|
60
55
|
{
|
|
61
|
-
const logCleaned = (
|
|
56
|
+
const logCleaned = stripAnsi(log);
|
|
62
57
|
let isMatch = false;
|
|
63
58
|
if (typeof isReadyLog === 'string') {
|
|
64
59
|
isMatch = logCleaned.includes(isReadyLog);
|
|
65
60
|
}
|
|
66
|
-
else if (
|
|
61
|
+
else if (isCallable(isReadyLog)) {
|
|
67
62
|
isMatch = isReadyLog(logCleaned);
|
|
68
63
|
}
|
|
69
64
|
else {
|
|
70
|
-
|
|
65
|
+
assert(false);
|
|
71
66
|
}
|
|
72
67
|
if (isMatch)
|
|
73
68
|
onReady();
|
|
@@ -100,7 +95,7 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
100
95
|
onError(new Error(errMsg), true);
|
|
101
96
|
}
|
|
102
97
|
else {
|
|
103
|
-
|
|
98
|
+
assert(isReady);
|
|
104
99
|
}
|
|
105
100
|
exitPromiseResolve();
|
|
106
101
|
});
|
|
@@ -131,7 +126,7 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
131
126
|
*/
|
|
132
127
|
resolve();
|
|
133
128
|
}, terminationTimeout);
|
|
134
|
-
|
|
129
|
+
assert(proc);
|
|
135
130
|
await stopProcess({
|
|
136
131
|
proc,
|
|
137
132
|
cwd,
|
|
@@ -145,7 +140,6 @@ function runCommandLongRunning({ cmd, cwd, killPort, isReadyLog, isReadyTimeout,
|
|
|
145
140
|
return promise;
|
|
146
141
|
}
|
|
147
142
|
}
|
|
148
|
-
exports.runCommandLongRunning = runCommandLongRunning;
|
|
149
143
|
function stopProcess({ proc, cwd, cmd, force, onTerminationError, }) {
|
|
150
144
|
let resolve;
|
|
151
145
|
const promise = new Promise((_resolve, _reject) => {
|
|
@@ -160,8 +154,8 @@ function stopProcess({ proc, cwd, cmd, force, onTerminationError, }) {
|
|
|
160
154
|
proc.on('close', onProcessClose);
|
|
161
155
|
proc.on('exit', onProcessClose);
|
|
162
156
|
const { pid } = proc;
|
|
163
|
-
|
|
164
|
-
if (
|
|
157
|
+
assert(pid);
|
|
158
|
+
if (isWindows()) {
|
|
165
159
|
// - https://github.com/nodejs/node/issues/3617#issuecomment-377731194
|
|
166
160
|
// - https://stackoverflow.com/questions/23706055/why-can-i-not-kill-my-child-process-in-nodejs-on-windows/28163919#28163919
|
|
167
161
|
// - taskkill seems to be buggy in many ways:
|
|
@@ -185,22 +179,22 @@ function stopProcess({ proc, cwd, cmd, force, onTerminationError, }) {
|
|
|
185
179
|
// ERROR: The process "6564" not found.
|
|
186
180
|
// ```
|
|
187
181
|
// There doesn't seem to be an option to suppress these errors: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill#parameters
|
|
188
|
-
|
|
189
|
-
|
|
182
|
+
assert(typeof pid === 'number');
|
|
183
|
+
spawn('taskkill', ['/pid', String(pid), '/f', '/t'], {
|
|
190
184
|
stdio: [
|
|
191
|
-
'ignore',
|
|
185
|
+
'ignore', // stdin
|
|
192
186
|
// Ignore following log to avoid polluting non-error logs. (Setting 'inherit' instead of 'ignore' attaches stdout to the root process and not to `proc` which is why the stdout of taskkill isn't intercepted by `proc.stdout.on('data', () => /* ... */)`.)
|
|
193
187
|
// ```
|
|
194
188
|
// SUCCESS: The process with PID 6932 (child process of PID 2744) has been terminated.
|
|
195
189
|
// ```
|
|
196
|
-
'ignore',
|
|
190
|
+
'ignore', // stdout
|
|
197
191
|
// Ignoring stderr doesn't solve the problem that taskkill makes the process exit with code 1
|
|
198
192
|
'inherit', // stderr
|
|
199
193
|
],
|
|
200
194
|
});
|
|
201
195
|
}
|
|
202
196
|
else {
|
|
203
|
-
|
|
197
|
+
assert(typeof pid === 'number');
|
|
204
198
|
const processGroup = -1 * pid;
|
|
205
199
|
const signal = force ? 'SIGKILL' : 'SIGTERM';
|
|
206
200
|
process.kill(processGroup, signal);
|
|
@@ -223,10 +217,24 @@ function stopProcess({ proc, cwd, cmd, force, onTerminationError, }) {
|
|
|
223
217
|
return promise;
|
|
224
218
|
}
|
|
225
219
|
async function killByPort(port) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
await
|
|
220
|
+
assert(isLinux());
|
|
221
|
+
assert(port);
|
|
222
|
+
await runCommandShortLived(`fuser -k ${port}/tcp`, { swallowError: true, timeout: 10 * 1000 });
|
|
229
223
|
}
|
|
230
224
|
function isSuccessCode(code) {
|
|
231
|
-
return code === 0 || code === null || (code === 1 &&
|
|
225
|
+
return code === 0 || code === null || (code === 1 && isWindows());
|
|
226
|
+
}
|
|
227
|
+
/* Doesn't work:
|
|
228
|
+
const spawn2: typeof spawn_ = (...args) => spawn_(...args)
|
|
229
|
+
const spawn3: typeof spawn_ = function(...args) { return spawn_(...args) }
|
|
230
|
+
//*/
|
|
231
|
+
function spawn(command, args, options) {
|
|
232
|
+
// Workaround for Node.js regression:
|
|
233
|
+
// - https://github.com/nodejs/node/issues/52475
|
|
234
|
+
// - https://github.com/prebuild/prebuildify/issues/83#issuecomment-2056607495
|
|
235
|
+
if (isWindows())
|
|
236
|
+
options.shell = true;
|
|
237
|
+
// Needed for spawn_() to return ChildProcessWithoutNullStreams instead of ChildProcess
|
|
238
|
+
assert(hasProp(options, 'stdio', 'undefined'));
|
|
239
|
+
return spawn_(command, args, options);
|
|
232
240
|
}
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const genPromise_1 = require("./genPromise");
|
|
6
|
-
const humanizeTime_1 = require("./humanizeTime");
|
|
1
|
+
export { runCommandShortLived };
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import { genPromise } from './genPromise.js';
|
|
4
|
+
import { humanizeTime } from './humanizeTime.js';
|
|
7
5
|
function runCommandShortLived(cmd, { swallowError = false, timeout = 5000, cwd = process.cwd(), } = {}) {
|
|
8
|
-
const { promise, resolve, reject } =
|
|
6
|
+
const { promise, resolve, reject } = genPromise();
|
|
9
7
|
const t = setTimeout(() => {
|
|
10
|
-
console.error(`Command call \`${cmd}\` (${cwd}) timed out after ${
|
|
8
|
+
console.error(`Command call \`${cmd}\` (${cwd}) timed out after ${humanizeTime(timeout)}`);
|
|
11
9
|
reject();
|
|
12
10
|
}, timeout);
|
|
13
11
|
const options = { cwd };
|
|
14
|
-
|
|
12
|
+
exec(cmd, options, (err, stdout, stderr) => {
|
|
15
13
|
clearTimeout(t);
|
|
16
14
|
if (err || stderr) {
|
|
17
15
|
if (swallowError) {
|
|
@@ -36,4 +34,3 @@ function runCommandShortLived(cmd, { swallowError = false, timeout = 5000, cwd =
|
|
|
36
34
|
});
|
|
37
35
|
return promise;
|
|
38
36
|
}
|
|
39
|
-
exports.runCommandShortLived = runCommandShortLived;
|
package/dist/utils/sleep.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
package/dist/utils/trackLogs.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
trackLogs();
|
|
3
2
|
// https://stackoverflow.com/questions/45395369/how-to-get-console-log-line-numbers-shown-in-nodejs/75109905#75109905
|
|
4
3
|
function trackLogs() {
|
|
@@ -19,3 +18,4 @@ function trackLogs() {
|
|
|
19
18
|
});
|
|
20
19
|
Error.stackTraceLimit = Infinity;
|
|
21
20
|
}
|
|
21
|
+
export {};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from './utils/sleep.js';
|
|
2
|
+
export * from './utils/runCommand.js';
|
|
3
|
+
export * from './utils/runCommandShortLived.js';
|
|
4
|
+
export * from './utils/runCommandLongRunning.js';
|
|
5
|
+
export * from './utils/assert.js';
|
|
6
|
+
export * from './utils/humanizeTime.js';
|
|
7
|
+
export * from './utils/isTTY.js';
|
|
8
|
+
export * from './utils/findFiles.js';
|
|
9
|
+
export * from './utils/logProgress.js';
|
|
10
|
+
export * from './utils/cliOptions.js';
|
|
11
|
+
export * from './utils/fsWindowsBugWorkaround.js';
|
|
12
|
+
export * from './utils/isObject.js';
|
|
13
|
+
export * from './utils/isCallable.js';
|
|
14
|
+
export * from './utils/platform.js';
|
|
15
|
+
export * from './utils/isMinNodeVersion.js';
|
|
16
|
+
export * from './utils/hasProp.js';
|