Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 944b516

Browse files
committed
Add test coverage, improve test coverage of process-name, and args
1 parent 773f21a commit 944b516

File tree

7 files changed

+331
-29
lines changed

7 files changed

+331
-29
lines changed

src/packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"scripts": {
3232
"tsc": "tsc --build",
33-
"test": "nyc npm run mocha",
33+
"test": "nyc --reporter lcov npm run mocha",
3434
"mocha": "cross-env TS_NODE_FILES=true mocha --exit --check-leaks --throw-deprecation --trace-warnings --require ts-node/register 'tests/**/*.test.ts'",
3535
"start": "cross-env node --require ts-node/register --inspect src/cli.ts"
3636
},

src/packages/cli/src/args.ts

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
// `import Yargs from "yargs"` is the Yargs singleton and namespace
2+
// `import yargs from "yargs/yargs"` is the non-singleton interface
3+
// See https://github.com/yargs/yargs/issues/1648
4+
import Yargs, { Options } from "yargs";
5+
import yargs from "yargs/yargs";
6+
17
import { TruffleColors } from "@ganache/colors";
2-
import yargs, { Options } from "yargs";
38
import {
49
DefaultFlavor,
510
FilecoinFlavorName,
@@ -26,7 +31,7 @@ marked.setOptions({
2631
})
2732
});
2833

29-
const wrapWidth = Math.min(120, yargs.terminalWidth());
34+
const wrapWidth = Math.min(120, Yargs.terminalWidth());
3035
const NEED_HELP = "Need more help? Reach out to the Truffle community at";
3136
const COMMUNITY_LINK = "https://trfl.io/support";
3237

@@ -43,7 +48,7 @@ const highlight = (t: string) => unescapeEntities(marked.parseInline(t));
4348
const center = (str: string) =>
4449
" ".repeat(Math.max(0, Math.floor((wrapWidth - str.length) / 2))) + str;
4550

46-
const addAliases = (args: yargs.Argv<{}>, aliases: string[], key: string) => {
51+
const addAliases = (args: Yargs.Argv<{}>, aliases: string[], key: string) => {
4752
const options = { hidden: true, alias: key };
4853
return aliases.reduce((args, a) => args.option(a, options), args);
4954
};
@@ -54,7 +59,7 @@ function processOption(
5459
group: string,
5560
option: string,
5661
optionObj: Definitions<Base.Config>[string],
57-
argv: yargs.Argv,
62+
argv: Yargs.Argv,
5863
flavor: string
5964
) {
6065
if (optionObj.disableInCLI !== true) {
@@ -122,7 +127,7 @@ function applyDefaults(
122127
flavorDefaults:
123128
| typeof DefaultOptionsByName[keyof typeof DefaultOptionsByName]
124129
| typeof _DefaultServerOptions,
125-
flavorArgs: yargs.Argv<{}>,
130+
flavorArgs: Yargs.Argv<{}>,
126131
flavor: keyof typeof DefaultOptionsByName
127132
) {
128133
for (const category in flavorDefaults) {
@@ -160,8 +165,9 @@ export default function (
160165

161166
// disable dot-notation because yargs just can't coerce args properly...
162167
// ...on purpose! https://github.com/yargs/yargs/issues/1021#issuecomment-352324693
163-
yargs
168+
const yargsParser = yargs()
164169
.parserConfiguration({ "dot-notation": false })
170+
.exitProcess(false)
165171
.strict()
166172
.usage(versionUsageOutputText)
167173
.epilogue(
@@ -188,12 +194,9 @@ export default function (
188194
command = ["$0", flavor];
189195
defaultPort = 8545;
190196
break;
191-
default:
192-
command = flavor;
193-
defaultPort = 8545;
194197
}
195198

196-
yargs.command(
199+
yargsParser.command(
197200
command,
198201
chalk`Use the {bold ${flavor}} flavor of Ganache`,
199202
flavorArgs => {
@@ -214,14 +217,19 @@ export default function (
214217
description: chalk`Port to listen on.${EOL}{dim deprecated aliases: --port}${EOL}`,
215218
alias: ["p", "port"],
216219
type: "number",
217-
default: defaultPort
220+
default: defaultPort,
221+
// `string: true` to allow raw value to be used in validation below
222+
// (otherwise string values becomes NaN)
223+
string: true,
224+
coerce: port => (isFinite(port) ? +port : port)
218225
})
219226
.check(argv => {
220227
const { "server.port": port, "server.host": host } = argv;
221-
if (port < 1 || port > 65535) {
222-
throw new Error(`Invalid port number '${port}'`);
228+
if (!isFinite(port) || port < 1 || port > 65535) {
229+
throw new Error(
230+
`Port should be >= 0 and < 65536. Received ${port}.`
231+
);
223232
}
224-
225233
if (host.trim() === "") {
226234
throw new Error("Cannot leave host blank; please provide a host");
227235
}
@@ -244,7 +252,7 @@ export default function (
244252
);
245253
}
246254

247-
yargs
255+
yargsParser
248256
.command(
249257
"instances",
250258
highlight(
@@ -272,6 +280,14 @@ export default function (
272280
stopArgs.action = "stop";
273281
}
274282
)
283+
.check(instancesArgs => {
284+
if (instancesArgs["_"].length <= 1) {
285+
throw new Error(
286+
"No sub-command given. See `ganache instances --help` for more information."
287+
);
288+
}
289+
return true;
290+
})
275291
.version(false);
276292
}
277293
)
@@ -280,7 +296,7 @@ export default function (
280296
.wrap(wrapWidth)
281297
.version(version);
282298

283-
const parsedArgs = yargs.parse(rawArgs);
299+
const parsedArgs = yargsParser.parse(rawArgs);
284300

285301
let finalArgs: GanacheArgs;
286302
if (parsedArgs.action === "stop") {
@@ -308,7 +324,7 @@ export default function (
308324
>)
309325
};
310326
} else {
311-
throw new Error(`Unknown action: ${parsedArgs.action}`);
327+
finalArgs = { action: "help" };
312328
}
313329

314330
return finalArgs;

src/packages/cli/src/cli.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
import { TruffleColors } from "@ganache/colors";
1818
import { table } from "table";
1919
import chalk from "chalk";
20+
import { GanacheArgs } from "./types";
2021

2122
const logAndForceExit = (messages: any[], exitCode = 0) => {
2223
// https://nodejs.org/api/process.html#process_process_exit_code
@@ -60,7 +61,11 @@ const detailedVersion = `ganache v${version} (@ganache/cli: ${cliVersion}, @gana
6061
const isDocker =
6162
"DOCKER" in process.env && process.env.DOCKER.toLowerCase() === "true";
6263

63-
const argv = args(detailedVersion, isDocker);
64+
let argv: GanacheArgs;
65+
try {
66+
argv = args(detailedVersion, isDocker);
67+
} catch (err: any) {}
68+
6469
if (argv.action === "start") {
6570
const flavor = argv.flavor;
6671
const cliSettings = argv.server;

src/packages/cli/src/process-name.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
function pick(source: string[]) {
2-
const partIndex = Math.floor(Math.random() * source.length);
1+
function pick(source: string[], random: () => number) {
2+
const partIndex = Math.floor(random() * source.length);
33
return source[partIndex];
44
}
55
/**
66
* Generates a random name to assign to an instance of Ganache. The name is
77
* generated from an adjective, a flavor and a type of desert, in the form of
88
* `<adjective>_<flavor>_<type>`, eg., `salted_caramel_ganache`.
99
*/
10-
export default function createInstanceName() {
11-
const name = [adjectives, flavors, kinds].map(pick).join("_");
10+
export default function createInstanceName(random: () => number = Math.random) {
11+
const name = [adjectives, flavors, kinds]
12+
.map(source => pick(source, random))
13+
.join("_");
1214
return name;
1315
}
1416

1517
const adjectives = [
1618
"baked",
1719
"candied",
20+
"creamy",
1821
"deepfried",
1922
"frozen",
2023
"hot",
@@ -48,7 +51,7 @@ const flavors = [
4851
"orange",
4952
"peanut",
5053
"plum",
51-
"poppy-seed",
54+
"poppyseed",
5255
"rhubarb",
5356
"strawberry",
5457
"sugar",

src/packages/cli/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type CliServerOptions = {
66
port: number;
77
};
88

9-
type Action = "start" | "start-detached" | "list" | "stop";
9+
type Action = "start" | "start-detached" | "list" | "stop" | "help";
1010

1111
type AbstractArgs<TAction = Action> = {
1212
action: TAction;
@@ -21,6 +21,7 @@ export type StartArgs<TFlavorName extends FlavorName> =
2121
export type GanacheArgs =
2222
| (AbstractArgs<"stop"> & { name: string })
2323
| AbstractArgs<"list">
24+
| AbstractArgs<"help">
2425
| StartArgs<FlavorName>;
2526

2627
export type CliSettings = CliServerOptions;

0 commit comments

Comments
 (0)