diff --git a/docs/api/js-utils.childoptions.cwd.md b/docs/api/js-utils.childoptions.cwd.md
deleted file mode 100644
index 690079b0..00000000
--- a/docs/api/js-utils.childoptions.cwd.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [@apextoaster/js-utils](./js-utils.md) > [ChildOptions](./js-utils.childoptions.md) > [cwd](./js-utils.childoptions.cwd.md)
-
-## ChildOptions.cwd property
-
-Signature:
-
-```typescript
-cwd: string;
-```
diff --git a/docs/api/js-utils.childoptions.env.md b/docs/api/js-utils.childoptions.env.md
deleted file mode 100644
index f93e870e..00000000
--- a/docs/api/js-utils.childoptions.env.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [@apextoaster/js-utils](./js-utils.md) > [ChildOptions](./js-utils.childoptions.md) > [env](./js-utils.childoptions.env.md)
-
-## ChildOptions.env property
-
-Signature:
-
-```typescript
-env: Array>;
-```
diff --git a/docs/api/js-utils.childoptions.md b/docs/api/js-utils.childoptions.md
index 02bb5595..baaa4c4f 100644
--- a/docs/api/js-utils.childoptions.md
+++ b/docs/api/js-utils.childoptions.md
@@ -7,7 +7,7 @@
Signature:
```typescript
-export interface ChildOptions
+export interface ChildOptions extends ChildProcessOptions
```
## Properties
@@ -16,7 +16,4 @@ export interface ChildOptions
| --- | --- | --- |
| [args](./js-utils.childoptions.args.md) | Array<string>
| |
| [command](./js-utils.childoptions.command.md) | string
| |
-| [cwd](./js-utils.childoptions.cwd.md) | string
| |
-| [env](./js-utils.childoptions.env.md) | Array<NameValuePair<string>>
| |
-| [timeout](./js-utils.childoptions.timeout.md) | number
| |
diff --git a/docs/api/js-utils.childoptions.timeout.md b/docs/api/js-utils.childoptions.timeout.md
deleted file mode 100644
index 77f66c81..00000000
--- a/docs/api/js-utils.childoptions.timeout.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [@apextoaster/js-utils](./js-utils.md) > [ChildOptions](./js-utils.childoptions.md) > [timeout](./js-utils.childoptions.timeout.md)
-
-## ChildOptions.timeout property
-
-Signature:
-
-```typescript
-timeout: number;
-```
diff --git a/docs/api/js-utils.childspawner.md b/docs/api/js-utils.childspawner.md
index 4d062bd0..b6be08e9 100644
--- a/docs/api/js-utils.childspawner.md
+++ b/docs/api/js-utils.childspawner.md
@@ -7,5 +7,5 @@
Signature:
```typescript
-export declare type ChildSpawner = typeof spawn;
+export declare type ChildSpawner = (command: string, args: Array, options: Partial) => ChildStreams;
```
diff --git a/docs/api/js-utils.waitforchild.md b/docs/api/js-utils.waitforchild.md
index 7740ff62..6adac2d4 100644
--- a/docs/api/js-utils.waitforchild.md
+++ b/docs/api/js-utils.waitforchild.md
@@ -7,14 +7,14 @@
Signature:
```typescript
-export declare function waitForChild(child: ChildProcessWithoutNullStreams): Promise;
+export declare function waitForChild(child: ChildStreams): Promise;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| child | ChildProcessWithoutNullStreams
| |
+| child | ChildStreams
| |
Returns:
diff --git a/src/utils/Child.ts b/src/utils/Child.ts
index 2b8ea0e3..05b62744 100644
--- a/src/utils/Child.ts
+++ b/src/utils/Child.ts
@@ -1,4 +1,4 @@
-import { ChildProcessWithoutNullStreams, spawn } from 'child_process';
+import { ChildProcessWithoutNullStreams, spawn, ChildProcess } from 'child_process';
import { BaseError } from 'noicejs';
import { Writable } from 'stream';
@@ -7,28 +7,37 @@ import { ChildProcessError } from '../error/ChildProcessError';
import { encode } from './Buffer';
import { NameValuePair } from './Map';
-export interface ChildOptions {
- args: Array;
- command: string;
+export interface ChildProcessOptions {
cwd: string;
env: Array>;
timeout: number;
}
+export interface ChildOptions extends ChildProcessOptions {
+ args: Array;
+ command: string;
+}
+
export interface ChildResult {
status: number;
stderr: string;
stdout: string;
}
-export type ChildSpawner = typeof spawn;
+export type ChildStreams = ChildProcessWithoutNullStreams;
+
+export type ChildSpawner = (
+ command: string,
+ args: Array,
+ options: Partial
+) => ChildStreams;
const CHILD_ENCODING = 'utf-8';
const CHILD_EVENT = 'child process emitted error event';
const CHILD_STATUS = 'child process exited with error status';
const CHILD_OUTPUT = 'child process emitted error output';
-export function waitForChild(child: ChildProcessWithoutNullStreams): Promise {
+export function waitForChild(child: ChildStreams): Promise {
return new Promise((res, rej) => {
const stderr: Array = [];
const stdout: Array = [];
diff --git a/test/utils/TestChild.ts b/test/utils/TestChild.ts
new file mode 100644
index 00000000..69f49d12
--- /dev/null
+++ b/test/utils/TestChild.ts
@@ -0,0 +1,56 @@
+import { expect } from 'chai';
+
+import { mustExist, Optional } from '../../src/utils';
+import { ChildStreams, waitForChild } from '../../src/utils/Child';
+import { describeLeaks, itLeaks } from '../helpers/async';
+import { ChildProcessError } from '../../src';
+
+type Closer = (status: number) => Promise;
+
+function createChild(): ChildStreams & { closer: Optional } {
+ return {
+ closer /* Optional */ : undefined,
+ on(event: string, fn: Closer) {
+ if (event === 'close') {
+ this.closer = fn;
+ }
+ },
+ stderr: {
+ on() {
+ /* noop */
+ },
+ },
+ stdout: {
+ on() {
+ /* noop */
+ },
+ },
+ /* eslint-disable @typescript-eslint/no-explicit-any */
+ } as any;
+}
+
+describeLeaks('child process utils', async () => {
+ describeLeaks('wait for child helper', async () => {
+ itLeaks('should read stdout data', async () => {
+ const child = createChild();
+
+ const resultPromise = waitForChild(child);
+ await mustExist(child.closer)(0);
+
+ const result = await resultPromise;
+ expect(result.status).to.equal(0);
+ });
+
+ itLeaks('should read stderr data');
+ itLeaks('should resolve on success status');
+
+ itLeaks('should reject on failure status', async () => {
+ const child = createChild();
+
+ const resultPromise = waitForChild(child);
+ await mustExist(child.closer)(1);
+
+ return expect(resultPromise).to.eventually.be.rejectedWith(ChildProcessError);
+ });
+ });
+});