@j-o-r/sh 1.1.24 → 1.1.25
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/lib/SHDispatch.js +1 -1
- package/lib/SHExecute.js +7 -9
- package/lib/Test.js +22 -11
- package/package.json +1 -1
- package/types/Test.d.ts +1 -0
package/lib/SHDispatch.js
CHANGED
|
@@ -114,7 +114,7 @@ class SHDispatch {
|
|
|
114
114
|
* @returns {SHDispatch}
|
|
115
115
|
*/
|
|
116
116
|
options(options, prefix) {
|
|
117
|
-
if (
|
|
117
|
+
if (typeof prefix === 'string') {
|
|
118
118
|
this.#prefix = prefix;
|
|
119
119
|
}
|
|
120
120
|
if (options.stdio && typeof options.stdio === 'string') {
|
package/lib/SHExecute.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawnSync, spawn} from 'node:child_process';
|
|
1
|
+
import { spawnSync, spawn } from 'node:child_process';
|
|
2
2
|
|
|
3
3
|
// Local helpers
|
|
4
4
|
const isFinitePosInt = (n) => Number.isFinite(n) && n >= 0;
|
|
@@ -19,15 +19,13 @@ const parseDuration = (d) => {
|
|
|
19
19
|
const childrenOf = (pid) => new Promise((resolve, reject) => {
|
|
20
20
|
const p = spawn('pgrep', ['-P', String(pid)], { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
21
21
|
const out = [];
|
|
22
|
-
p.stdout.on('data', (
|
|
22
|
+
p.stdout.on('data', (chunk) => out.push(chunk));
|
|
23
23
|
p.on('close', (code) => {
|
|
24
24
|
if (code === 0) {
|
|
25
25
|
const ids = Buffer.concat(out).toString('utf8').trim().split(/\s+/).map(Number).filter(Boolean);
|
|
26
26
|
resolve(ids);
|
|
27
27
|
} else if (code === 1) {
|
|
28
|
-
resolve([]); // no children
|
|
29
|
-
} else {
|
|
30
|
-
reject(new Error(`pgrep -P ${pid} failed with code ${code}`));
|
|
28
|
+
resolve([]); // no children or error
|
|
31
29
|
}
|
|
32
30
|
});
|
|
33
31
|
p.on('error', reject);
|
|
@@ -103,7 +101,7 @@ class SHExecute {
|
|
|
103
101
|
const shellOpt = this.#options?.shell;
|
|
104
102
|
if (shellOpt) {
|
|
105
103
|
const sh = typeof shellOpt === 'string' ? shellOpt : 'bash';
|
|
106
|
-
const cmd = `${this.#prefix}; ${this.#command}
|
|
104
|
+
const cmd = this.#prefix ? `${this.#prefix}; ${this.#command}` : this.#command;
|
|
107
105
|
return spawnSync(sh, ['-c', cmd], options);
|
|
108
106
|
}
|
|
109
107
|
// no-shell mode
|
|
@@ -139,7 +137,7 @@ class SHExecute {
|
|
|
139
137
|
const shellOpt = this.#options?.shell;
|
|
140
138
|
if (shellOpt) {
|
|
141
139
|
const sh = typeof shellOpt === 'string' ? shellOpt : 'bash';
|
|
142
|
-
const cmd = `${this.#prefix}; ${this.#command}
|
|
140
|
+
const cmd = this.#prefix ? `${this.#prefix}; ${this.#command}` : this.#command;
|
|
143
141
|
this.#proc = spawn(sh, ['-c', cmd], options);
|
|
144
142
|
} else {
|
|
145
143
|
this.#proc = spawn('/usr/bin/env', ['-S', this.#command], options);
|
|
@@ -199,9 +197,9 @@ class SHExecute {
|
|
|
199
197
|
resolve(stdout);
|
|
200
198
|
} else {
|
|
201
199
|
const stderrBuf = this.#stderrChunks.length ? Buffer.concat(this.#stderrChunks) : Buffer.alloc(0);
|
|
202
|
-
let stderr = stderrBuf.toString('utf8')
|
|
200
|
+
let stderr = stderrBuf.toString('utf8');
|
|
203
201
|
if (this.#truncated.stderr) stderr += '\n[stderr truncated]\n';
|
|
204
|
-
reject(new Error(`
|
|
202
|
+
reject(new Error(`Command failed with code ${code}: ${stderr}`));
|
|
205
203
|
}
|
|
206
204
|
});
|
|
207
205
|
|
package/lib/Test.js
CHANGED
|
@@ -140,7 +140,9 @@ class Test {
|
|
|
140
140
|
const len = this.#tests.length;
|
|
141
141
|
for (; i < len; i++) {
|
|
142
142
|
this.#currentTest = i;
|
|
143
|
-
if (execute && !execute.includes(i))
|
|
143
|
+
if (execute && !execute.includes(i)) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
144
146
|
let duration = 0;
|
|
145
147
|
let start = getNow();
|
|
146
148
|
let executed = false;
|
|
@@ -179,9 +181,9 @@ class Test {
|
|
|
179
181
|
return this.#report();
|
|
180
182
|
}
|
|
181
183
|
/**
|
|
182
|
-
* @returns {Report}
|
|
184
|
+
* @returns {Promise<Report>}
|
|
183
185
|
*/
|
|
184
|
-
#report() {
|
|
186
|
+
async #report() {
|
|
185
187
|
let duration = 0;
|
|
186
188
|
let executed = 0;
|
|
187
189
|
const tests = this.#tests.length;
|
|
@@ -203,21 +205,29 @@ class Test {
|
|
|
203
205
|
console.log(`Total: ${tests} tests, executed: ${executed} in ${duration} ms - errors: ${errors}`);
|
|
204
206
|
if (tests !== executed) {
|
|
205
207
|
if (!this.#quiet) console.log('** Not all tests have been executed **');
|
|
206
|
-
return { tests, executed, duration, errors };
|
|
208
|
+
// return { tests, executed, duration, errors };
|
|
207
209
|
}
|
|
208
210
|
// Report on unresolved promises when NOT quiet
|
|
209
211
|
// This must be on a next tick because the current Promise (where this code is in) is not resolved yet
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
});
|
|
212
|
+
setTimeout(() => {
|
|
213
|
+
const count = this.#promiseTracker.report(true);
|
|
214
|
+
if (count > 0) {
|
|
215
|
+
console.log('--------------------------------------------------');
|
|
216
|
+
console.log(`${count} Unresolved Promises detected.`);
|
|
217
|
+
}
|
|
218
|
+
}, 10);
|
|
217
219
|
}
|
|
218
220
|
return { tests, executed, duration, errors };
|
|
219
221
|
}
|
|
220
222
|
|
|
223
|
+
unresolved() {
|
|
224
|
+
const count = this.#promiseTracker.report(true);
|
|
225
|
+
if (count > 0) {
|
|
226
|
+
console.log('--------------------------------------------------');
|
|
227
|
+
console.log(`${count} Unresolved Promises detected.`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
221
231
|
/**
|
|
222
232
|
* Empty tests
|
|
223
233
|
*/
|
|
@@ -225,6 +235,7 @@ class Test {
|
|
|
225
235
|
this.#tests = [];
|
|
226
236
|
this.#reports = [];
|
|
227
237
|
this.#errors = [];
|
|
238
|
+
this.#promiseTracker.reset();
|
|
228
239
|
}
|
|
229
240
|
/**
|
|
230
241
|
* Handle an error for the current test
|
package/package.json
CHANGED