Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - sramam/cli-inspector: Automate CLI testing with style · GitHub
Skip to content

Repository files navigation

cli-inspector

npm licensetravis statusBuild statusCoverage StatusDavidDavid
NPM

A library to help test CLI. Originally intended to test inquirer.js driven CLIs.

  • Should work for other CLI applications, but YMMV.
  • Developed on OSX, tested on *nix, windows.
  • Pull requests, DX enhancements welcomed.

Installation

npm install cli-inspector

Usage

constinspector=require('cli-inspector');inspector.run(cmd_line,// command-line to spawn child processinteractions,// array of Interactions (see below)options// extends child_process.spawnOptions);

Action

The gif below shows a build of cli-inspector, including tests, which use cli-inspector to test an example inquirer.js pizza-ordering application.

animated build

API documentation

inspector.run()

cli-inspector exposes a single method - run(). The idea is to provide it an array of in-sequence CLI interaction.

An example interactions array: src/test/fixtures/inquirer/interactions.js.

/** * run an cli-test. * 1. spawn a child process with the cmd_line specified. * 2. Provide an array of individual interactions. See [tests](test/fixtures/inquirer/interactions.ts) * for a working example. `npm run build` to see it in action. * interactions.forEach( (interaction) => { * - wait for the prompt on interaction.stdout (string/regexp) * - pipe interaction.input to stdin * - wait for interaction.stdout/interaction.stderr if specified. * rinse and repeat * 3. Options provide control over the inspector and the child_process. * The most important control provided by `cli-inspector` are * - `delta`, the polling interval. Defaults to 1000 * - `timeout`, the time to wait in ms till * @export * @param {string} cmd_line * @param {Interaction[]} interactions * @param {Options} [options] */exportasyncfunctionrun(cmd_line: string,interactions: Interaction[],options?: Options);

Interaction(s)

exportinterfaceInteraction{/** * await prompt before processing this element * * @type {(string | RegExp)} */prompt: string|RegExp;/** * when prompt found, input is piped into stdin of child process. * If an array, each element is sent with the delta timeout * * @type {((string | RegExp)[] | (string | RegExp))} */input: (string|RegExp)[]|(string|RegExp);/** * (Optional) message to await on stdout of child process, after input * * @type {(string | RegExp)} */stdout?: string|RegExp;/** * (Optional) message to await on stderr of child process, after input * * @type {(string | RegExp)} */stderr?: string|RegExp;/** * optional timeout for this step. * * @type {(number | null)} * @default (value of options.timeout) */timeout?: number|null;/** * debug this step only. useful to find problems deep in an interaction chain. * * @type {boolean} * @default false */debugStep?: boolean;}

Options

exportinterfaceOptionsextendsSpawnOptions{/** * prints all child_process stdin/stdout/stderr to process stdout/stderr * * @type {boolean} * @default false */debug?: boolean;/** * Total timeout for each prompt-input-response sequence. * Specified in milliseconds * Can also be customized per interaction, but this sets the default value * for all interactions when not specified. * * @type {number} * @default 5000 */timeout?: number;/** * delta time between polling intervals and between keyboard sequences. * Specified in milliseconds * * @type {number} * @default 1000 */delta?: number;/** * Normally, the child process is killed on exit. This allows control. * Generally, this is not very useful except for interactive debugging. * * @type {boolean} * @default false */killOnExit?: boolean;}

Usage notes

CLIs have control sequences that make exact matching very cumbersome to create and maintain. It's much more convenient to use RegExps with wildcards and keywords.

This works well, but a few cautions:

  1. Prefer [\s\S]* to .* with regular expressions that match multi-line strings with terminal control characters.
  2. Escape all regexp special characters. There are a surprising number of them in regular CLIs. The set you should watch for: ^?[]()-{}!,*.
  3. Currently, the spawned process inserts a \n at column 80. The spawn operation however does not expose the underying TTY or control over it. Until we find a way around, the simplest thing is to add the [\n]? as an optional character in the match sequence.
  4. The interactions array is a command-response sequence. Creating it can get very complicated quickly. To help, cli-inspector adds a details object to erros thrown. Specifically, details.transcript, which records a step-by-step pattern match, making it easier to see what is actually being seen. A sample is shown below:
// Using err.details to get inspector state and debugging insight.try{inspector.run(cmd_line,interactions,options);}catch(err){console.log(JSON.stringify(err.details,null,2));throwerr;}

Develop

git clone https://github.com/tufan-io/cli-inspector
cd cli-inspector
npm i
npm run build

How does it work?

  • Spawns a child process with the supplied command line, under control of the cli-inspector.
  • Pipes stdin, stdout and stderr appropriately.
+---------------+
| cli-inspector | +---------------+
| | stdin | child process |
| +----------------------> |
| | stdout | |
| <----------------------+ |
| | stderr | |
| <----------------------+ |
+---------------+ +---------------+
  • Iterates over the supplied interactions, await interaction.prompt (on stdout) send interaction.userInput (on stdin) await interaction.response (on stdout) or interaction.error (on stderr)
  • kills child-process on completion.

There are multiple debug controls provided, please look at the code or ask questions!

License

Apache 2.0

Support

Bugs, PRs, comments, suggestions welcomed!

About

Automate CLI testing with style

Resources

Stars

4 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages