first-base 0.2.0 → 1.4.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/README.md CHANGED
@@ -111,6 +111,19 @@ run.write("2 + 2\n"); // Write 2 + 2 then press enter
111
111
  await run.outputContains("4");
112
112
  ```
113
113
 
114
+ ### `RunContext#close(stream: 'stdin' | 'stdout' | 'stderr')`
115
+
116
+ Close one of the processes's associated stdio streams.
117
+
118
+ #### Usage
119
+
120
+ ```js
121
+ const run = spawn("node", ["-i"]); // start Node.js REPL
122
+ await run.outputContains("> "); // Wait until prompt appears
123
+ run.close("stdin"); // Like pressing Ctrl+D; sends EOF
124
+ await run.completion;
125
+ ```
126
+
114
127
  ### `RunContext#kill(signal?: string)`
115
128
 
116
129
  Kills the process. If no signal is specified, it defaults to `"SIGINT"`.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export type Options = {
8
8
  shell?: boolean | string;
9
9
  windowsVerbatimArguments?: boolean;
10
10
  windowsHide?: boolean;
11
+ pty?: boolean;
11
12
  };
12
13
 
13
14
  export type RunContext = {
@@ -23,6 +24,7 @@ export type RunContext = {
23
24
  clearOutputContainsBuffer(): void;
24
25
  // TODO: Should be string | Buffer, but idk how to use Buffer since they might not be using node types
25
26
  write(data: any): void;
27
+ close(stream: "stdin" | "stdout" | "stderr"): void;
26
28
  kill(signal?: string): void;
27
29
  };
28
30
 
package/dist/index.js CHANGED
@@ -1,37 +1,31 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
-
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
5
4
  var normalSpawn = require("child_process").spawn;
5
+ var ptySpawn = require("node-pty").spawn;
6
+ var stripAnsi = require("strip-ansi");
6
7
 
7
- var stripAnsi = require("strip-ansi"); // Run a child process and return a "run context" object
8
+ // Run a child process and return a "run context" object
8
9
  // to interact with it. Function signature is the same as
9
10
  // child_process spawn, except you can pass `pty: true` in
10
11
  // options to run the process in a psuedo-tty.
11
-
12
-
13
12
  var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
14
13
  var args;
15
14
  var options;
16
-
17
15
  if (Array.isArray(argsOrOptions)) {
18
16
  args = argsOrOptions;
19
17
  } else if (_typeof(argsOrOptions) === "object") {
20
18
  options = argsOrOptions;
21
19
  }
22
-
23
20
  if (passedOptions && !options) {
24
21
  options = passedOptions;
25
22
  }
26
-
27
23
  if (!args) {
28
24
  args = [];
29
25
  }
30
-
31
26
  if (!options) {
32
27
  options = {};
33
28
  }
34
-
35
29
  var child;
36
30
  var stdin;
37
31
  var stdout;
@@ -41,15 +35,12 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
41
35
  var _debug = false;
42
36
  var outputContainsBuffer = "";
43
37
  var pendingOutputContainsRequests = new Set();
44
-
45
38
  var debugLog = function debugLog() {
46
39
  if (_debug) {
47
40
  var _console;
48
-
49
41
  (_console = console).log.apply(_console, arguments);
50
42
  }
51
43
  };
52
-
53
44
  var runContext = {
54
45
  result: {
55
46
  // All of the stdout and stderr the process has written so far.
@@ -75,17 +66,14 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
75
66
  var request = {
76
67
  value: value
77
68
  };
78
-
79
69
  request.resolve = function () {
80
- pendingOutputContainsRequests.delete(request);
70
+ pendingOutputContainsRequests["delete"](request);
81
71
  resolve();
82
72
  };
83
-
84
73
  request.reject = function () {
85
- pendingOutputContainsRequests.delete(request);
74
+ pendingOutputContainsRequests["delete"](request);
86
75
  reject();
87
76
  };
88
-
89
77
  pendingOutputContainsRequests.add(request);
90
78
  });
91
79
  },
@@ -96,23 +84,48 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
96
84
  write: function write(data) {
97
85
  stdin.write(data);
98
86
  },
87
+ // Call this function to close stdin, stdout, or stderr.
88
+ close: function close(stream) {
89
+ switch (String(stream).toLowerCase()) {
90
+ case "stdin":
91
+ {
92
+ stdin.end();
93
+ break;
94
+ }
95
+ case "stdout":
96
+ {
97
+ stdout.end();
98
+ break;
99
+ }
100
+ case "stderr":
101
+ {
102
+ stderr.end();
103
+ break;
104
+ }
105
+ default:
106
+ {
107
+ throw new Error("Invalid stream name: '".concat(stream, "'. Valid names are 'stdin', 'stdout', or 'stderr'."));
108
+ }
109
+ }
110
+ },
99
111
  // Call this function to send a signal to the child process.
100
112
  // You can pass "SIGTERM", "SIGKILL", etc. Defaults to "SIGINT".
101
113
  kill: function kill() {
102
114
  var signal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "SIGINT";
103
-
104
115
  if (running) {
105
116
  child.kill(signal);
106
117
  }
107
-
108
118
  if (unreffable) {
109
119
  unreffable.unref();
110
120
  }
111
121
  }
112
122
  };
113
-
114
123
  if (options.pty) {
115
- throw new Error("pty mode is no longer supported due to lack of support for new node.js versions in the node-pty module");
124
+ child = ptySpawn(cmd, args, options);
125
+ stdin = child;
126
+ stdout = child;
127
+ stderr = null; // no way to tell between stdout and stderr with pty
128
+ unreffable = child.socket;
116
129
  } else {
117
130
  child = normalSpawn(cmd, args, options);
118
131
  stdin = child.stdin;
@@ -120,9 +133,7 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
120
133
  stderr = child.stderr;
121
134
  unreffable = child;
122
135
  }
123
-
124
136
  running = true;
125
-
126
137
  var checkForPendingOutputRequestsToResolve = function checkForPendingOutputRequestsToResolve() {
127
138
  pendingOutputContainsRequests.forEach(function (request) {
128
139
  if (typeof request.value === "string") {
@@ -136,16 +147,13 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
136
147
  }
137
148
  });
138
149
  };
139
-
140
150
  stdout.setEncoding("utf-8");
141
-
142
151
  var handleStdoutData = function handleStdoutData(data) {
143
152
  runContext.result.stdout += data;
144
153
  outputContainsBuffer += data;
145
154
  debugLog("STDOUT: ".concat(data.toString()));
146
155
  checkForPendingOutputRequestsToResolve();
147
156
  };
148
-
149
157
  if (stdout.onData) {
150
158
  // the pty instance returned by node-pty
151
159
  // requires attaching handlers differently
@@ -153,11 +161,11 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
153
161
  } else {
154
162
  stdout.on("data", handleStdoutData);
155
163
  }
156
-
157
164
  if (stderr) {
158
- stderr.setEncoding("utf-8"); // this is never a pty instance,
159
- // so we don't need to deal with onData here:
165
+ stderr.setEncoding("utf-8");
160
166
 
167
+ // this is never a pty instance,
168
+ // so we don't need to deal with onData here:
161
169
  stderr.on("data", function (data) {
162
170
  runContext.result.stderr += data;
163
171
  outputContainsBuffer += data;
@@ -165,7 +173,6 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
165
173
  checkForPendingOutputRequestsToResolve();
166
174
  });
167
175
  }
168
-
169
176
  runContext.completion = new Promise(function (resolve) {
170
177
  var finish = function finish(reason) {
171
178
  debugLog("Process ".concat(reason));
@@ -176,7 +183,6 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
176
183
  request.reject(new Error("Child process ".concat(reason, " before its output contained the requested content: ").concat(request.value)));
177
184
  });
178
185
  };
179
-
180
186
  child.once("exit", function (code) {
181
187
  runContext.result.code = code;
182
188
  finish("exited");
@@ -188,7 +194,6 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
188
194
  });
189
195
  return runContext;
190
196
  };
191
-
192
197
  module.exports = {
193
198
  spawn: spawn
194
199
  };
@@ -9,6 +9,7 @@ export type Options = {
9
9
  shell?: ?boolean | string,
10
10
  windowsVerbatimArguments?: ?boolean,
11
11
  windowsHide?: ?boolean,
12
+ pty?: ?boolean,
12
13
  };
13
14
 
14
15
  export type RunContext = {
@@ -23,6 +24,7 @@ export type RunContext = {
23
24
  outputContains(value: string | RegExp): Promise<void>,
24
25
  clearOutputContainsBuffer(): void,
25
26
  write(data: string | Buffer): void,
27
+ close(stream: "stdin" | "stdout" | "stderr"): void,
26
28
  kill(signal?: string): void,
27
29
  };
28
30
 
package/package.json CHANGED
@@ -1,25 +1,26 @@
1
1
  {
2
2
  "name": "first-base",
3
- "version": "0.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Integration testing for CLI applications",
5
5
  "main": "dist/index.js",
6
6
  "repository": "https://github.com/suchipi/first-base",
7
- "author": "Lily Scott <me@suchipi.com>",
7
+ "author": "Lily Skye <me@suchipi.com>",
8
8
  "license": "MIT",
9
9
  "dependencies": {
10
+ "node-pty": "^1.0.0",
10
11
  "strip-ansi": "^5.0.0"
11
12
  },
12
13
  "devDependencies": {
13
- "@babel/cli": "^7.2.3",
14
- "@babel/core": "^7.2.2",
15
- "@babel/preset-env": "^7.2.3",
14
+ "@babel/cli": "^7.23.4",
15
+ "@babel/core": "^7.23.7",
16
+ "@babel/preset-env": "^7.23.8",
16
17
  "babel-core": "^7.0.0-bridge.0",
17
- "babel-jest": "^23.6.0",
18
- "eslint": "^5.11.1",
19
- "eslint-config-unobtrusive": "^1.2.2",
20
- "eslint-plugin-import": "^2.14.0",
21
- "jest": "^23.6.0",
22
- "prettier": "^1.15.3"
18
+ "babel-jest": "^29.7.0",
19
+ "eslint": "^8.56.0",
20
+ "eslint-config-unobtrusive": "^1.2.5",
21
+ "eslint-plugin-import": "^2.29.1",
22
+ "jest": "^29.7.0",
23
+ "prettier": "^3.2.4"
23
24
  },
24
25
  "scripts": {
25
26
  "build": "mkdir -p dist; rm -rf dist/*; babel src/index.js --out-dir dist && cp src/index.js.flow dist/ && cp src/index.d.ts dist/",