@tkeron/commands 0.3.0 → 0.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/.github/workflows/npm_deploy.yml +13 -7
- package/bun.lockb +0 -0
- package/changelog.md +16 -0
- package/examples/example.ts +116 -0
- package/package.json +9 -3
- package/readme.md +119 -2
- package/src/applyDefaults.ts +20 -0
- package/src/getCommandsFuncs.ts +92 -21
- package/src/getStart.ts +23 -28
- package/src/index.ts +1 -1
- package/src/parseArgs.ts +233 -0
- package/src/textFuncs.ts +32 -7
- package/src/types.ts +59 -4
- package/src/validateOptions.ts +39 -0
- package/tests/applyDefaults.test.ts +133 -0
- package/tests/backward-compatibility.test.ts +187 -0
- package/tests/example.e2e.test.ts +42 -0
- package/tests/getCommandsFuncs.test.ts +492 -0
- package/tests/getStart.test.ts +265 -0
- package/{src → tests/helpers}/testConstants.ts +1 -1
- package/tests/parseArgs.test.ts +565 -0
- package/tests/textFuncs.test.ts +179 -0
- package/tests/validateOptions.test.ts +157 -0
- package/tsconfig.json +2 -3
- package/src/example.e2e.test.ts +0 -37
- package/src/example.ts +0 -69
- package/src/getCommandsFuncs.test.ts +0 -94
- package/src/getStart.test.ts +0 -79
- package/src/textFuncs.test.ts +0 -59
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import {
|
|
2
|
+
command,
|
|
3
|
+
commands,
|
|
4
|
+
commandsCollection,
|
|
5
|
+
} from "./helpers/testConstants.js";
|
|
6
|
+
import {
|
|
7
|
+
buildDescriptionsText,
|
|
8
|
+
buildHelpText,
|
|
9
|
+
getCommandText,
|
|
10
|
+
} from "../src/textFuncs.js";
|
|
11
|
+
import { describe, expect, it } from "bun:test";
|
|
12
|
+
|
|
13
|
+
describe("text Functions", () => {
|
|
14
|
+
describe("getCommandText", () => {
|
|
15
|
+
it("should return command text", () => {
|
|
16
|
+
const result = getCommandText(command);
|
|
17
|
+
|
|
18
|
+
expect(result).toBe(
|
|
19
|
+
"command_1|al1|al2 [pos1] [pos2] [op1=opEx1] [op2=VALUE] ",
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return command text without aliases", () => {
|
|
24
|
+
const result = getCommandText({ ...command, aliases: [] });
|
|
25
|
+
|
|
26
|
+
expect(result).toBe(
|
|
27
|
+
"command_1 [pos1] [pos2] [op1=opEx1] [op2=VALUE] ",
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe("buildHelpText", () => {
|
|
32
|
+
it("should return help text", () => {
|
|
33
|
+
const result = buildHelpText(commands, commandsCollection);
|
|
34
|
+
expect(result).toBe(
|
|
35
|
+
"\nheader text...\nhelp line...\nhelp line...\nhelp line...\nfooter text...\n",
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
it("should return help text without headerText", () => {
|
|
39
|
+
const result = buildHelpText(
|
|
40
|
+
{ ...commands, headerText: "" },
|
|
41
|
+
commandsCollection,
|
|
42
|
+
);
|
|
43
|
+
expect(result).toBe(
|
|
44
|
+
"\n\nhelp line...\nhelp line...\nhelp line...\nfooter text...\n",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
it("should return help text without footerText", () => {
|
|
48
|
+
const result = buildHelpText(
|
|
49
|
+
{ ...commands, footerText: "" },
|
|
50
|
+
commandsCollection,
|
|
51
|
+
);
|
|
52
|
+
expect(result).toBe(
|
|
53
|
+
"\nheader text...\nhelp line...\nhelp line...\nhelp line...\n\n",
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe("buildDescriptionsText", () => {
|
|
58
|
+
it("should return description text", () => {
|
|
59
|
+
const result = buildDescriptionsText(commandsCollection);
|
|
60
|
+
expect(result).toBe("help line...\n".repeat(3));
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("should return empty string for empty collection", () => {
|
|
64
|
+
const result = buildDescriptionsText({});
|
|
65
|
+
expect(result).toBe("");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("getCommandText edge cases", () => {
|
|
70
|
+
it("should handle command with no options and no positioned args", () => {
|
|
71
|
+
const result = getCommandText({
|
|
72
|
+
...command,
|
|
73
|
+
options: [],
|
|
74
|
+
optionsExamples: [],
|
|
75
|
+
positionedArguments: [],
|
|
76
|
+
aliases: [],
|
|
77
|
+
});
|
|
78
|
+
expect(result).toBe("command_1 ");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should handle command with only aliases", () => {
|
|
82
|
+
const result = getCommandText({
|
|
83
|
+
...command,
|
|
84
|
+
options: [],
|
|
85
|
+
optionsExamples: [],
|
|
86
|
+
positionedArguments: [],
|
|
87
|
+
});
|
|
88
|
+
expect(result).toBe("command_1|al1|al2 ");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should use VALUE as default example when not provided", () => {
|
|
92
|
+
const result = getCommandText({
|
|
93
|
+
...command,
|
|
94
|
+
options: ["opt1"],
|
|
95
|
+
optionsExamples: [],
|
|
96
|
+
positionedArguments: [],
|
|
97
|
+
aliases: [],
|
|
98
|
+
});
|
|
99
|
+
expect(result).toBe("command_1 [opt1=VALUE] ");
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe("getCommandText with optionDefinitions", () => {
|
|
105
|
+
it("should format boolean flag with short flag", () => {
|
|
106
|
+
const command = {
|
|
107
|
+
...commandsCollection.command_1,
|
|
108
|
+
optionDefinitions: [
|
|
109
|
+
{
|
|
110
|
+
name: "verbose",
|
|
111
|
+
shortFlag: "v",
|
|
112
|
+
type: "boolean" as const,
|
|
113
|
+
description: "Verbose output",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
const result = getCommandText(command);
|
|
118
|
+
expect(result).toContain("--verbose");
|
|
119
|
+
expect(result).toContain("-v");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("should format string option with short flag", () => {
|
|
123
|
+
const command = {
|
|
124
|
+
...commandsCollection.command_1,
|
|
125
|
+
optionDefinitions: [
|
|
126
|
+
{
|
|
127
|
+
name: "output",
|
|
128
|
+
shortFlag: "o",
|
|
129
|
+
type: "string" as const,
|
|
130
|
+
description: "Output directory",
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
const result = getCommandText(command);
|
|
135
|
+
expect(result).toContain("--output");
|
|
136
|
+
expect(result).toContain("-o");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("should show required marker for required options", () => {
|
|
140
|
+
const command = {
|
|
141
|
+
...commandsCollection.command_1,
|
|
142
|
+
optionDefinitions: [
|
|
143
|
+
{
|
|
144
|
+
name: "config",
|
|
145
|
+
type: "string" as const,
|
|
146
|
+
description: "Config file",
|
|
147
|
+
required: true,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
const result = getCommandText(command);
|
|
152
|
+
expect(result).toContain("<config>");
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("should show optional marker for optional options", () => {
|
|
156
|
+
const command = {
|
|
157
|
+
...commandsCollection.command_1,
|
|
158
|
+
optionDefinitions: [
|
|
159
|
+
{
|
|
160
|
+
name: "format",
|
|
161
|
+
type: "string" as const,
|
|
162
|
+
description: "Output format",
|
|
163
|
+
required: false,
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
const result = getCommandText(command);
|
|
168
|
+
expect(result).toContain("[--format");
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should fall back to legacy format when no optionDefinitions", () => {
|
|
172
|
+
const command = {
|
|
173
|
+
...commandsCollection.command_1,
|
|
174
|
+
optionDefinitions: [],
|
|
175
|
+
};
|
|
176
|
+
const result = getCommandText(command);
|
|
177
|
+
expect(result).toContain("[op1=opEx1]");
|
|
178
|
+
});
|
|
179
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import type { Command, ParsedOptions } from "../src/types.js";
|
|
3
|
+
import { validateOptions } from "../src/validateOptions.js";
|
|
4
|
+
|
|
5
|
+
describe("validateOptions", () => {
|
|
6
|
+
let command: Command;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
command = {
|
|
10
|
+
name: "test",
|
|
11
|
+
description: "test",
|
|
12
|
+
aliases: [],
|
|
13
|
+
options: [],
|
|
14
|
+
optionsExamples: [],
|
|
15
|
+
positionedArguments: [],
|
|
16
|
+
optionDefinitions: [],
|
|
17
|
+
getHelpLine: () => "",
|
|
18
|
+
callback: () => {},
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should validate required option is present", () => {
|
|
23
|
+
command.optionDefinitions = [
|
|
24
|
+
{
|
|
25
|
+
name: "output",
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Output",
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
const parsed: ParsedOptions = { output: "dist" };
|
|
32
|
+
const result = validateOptions(parsed, command);
|
|
33
|
+
expect(result.valid).toBe(true);
|
|
34
|
+
expect(result.errors).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should fail when required option is missing", () => {
|
|
38
|
+
command.optionDefinitions = [
|
|
39
|
+
{
|
|
40
|
+
name: "output",
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Output",
|
|
43
|
+
required: true,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
const parsed: ParsedOptions = {};
|
|
47
|
+
const result = validateOptions(parsed, command);
|
|
48
|
+
expect(result.valid).toBe(false);
|
|
49
|
+
expect(result.errors).toContain("Required option 'output' is missing");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should validate multiple required options", () => {
|
|
53
|
+
command.optionDefinitions = [
|
|
54
|
+
{
|
|
55
|
+
name: "output",
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "Output",
|
|
58
|
+
required: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "input",
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Input",
|
|
64
|
+
required: true,
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
const parsed: ParsedOptions = { output: "dist" };
|
|
68
|
+
const result = validateOptions(parsed, command);
|
|
69
|
+
expect(result.valid).toBe(false);
|
|
70
|
+
expect(result.errors).toContain("Required option 'input' is missing");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should validate number type is valid", () => {
|
|
74
|
+
command.optionDefinitions = [
|
|
75
|
+
{
|
|
76
|
+
name: "port",
|
|
77
|
+
type: "number",
|
|
78
|
+
description: "Port",
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
const parsed: ParsedOptions = { port: 3000 };
|
|
82
|
+
const result = validateOptions(parsed, command);
|
|
83
|
+
expect(result.valid).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should fail when number type is NaN", () => {
|
|
87
|
+
command.optionDefinitions = [
|
|
88
|
+
{
|
|
89
|
+
name: "port",
|
|
90
|
+
type: "number",
|
|
91
|
+
description: "Port",
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
const parsed: ParsedOptions = { port: NaN };
|
|
95
|
+
const result = validateOptions(parsed, command);
|
|
96
|
+
expect(result.valid).toBe(false);
|
|
97
|
+
expect(result.errors).toContain("Option 'port' must be a valid number");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("should validate allowed values", () => {
|
|
101
|
+
command.optionDefinitions = [
|
|
102
|
+
{
|
|
103
|
+
name: "format",
|
|
104
|
+
type: "string",
|
|
105
|
+
description: "Format",
|
|
106
|
+
allowedValues: ["json", "xml", "yaml"],
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
const parsed: ParsedOptions = { format: "json" };
|
|
110
|
+
const result = validateOptions(parsed, command);
|
|
111
|
+
expect(result.valid).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should fail when value not in allowed values", () => {
|
|
115
|
+
command.optionDefinitions = [
|
|
116
|
+
{
|
|
117
|
+
name: "format",
|
|
118
|
+
type: "string",
|
|
119
|
+
description: "Format",
|
|
120
|
+
allowedValues: ["json", "xml", "yaml"],
|
|
121
|
+
},
|
|
122
|
+
];
|
|
123
|
+
const parsed: ParsedOptions = { format: "invalid" };
|
|
124
|
+
const result = validateOptions(parsed, command);
|
|
125
|
+
expect(result.valid).toBe(false);
|
|
126
|
+
expect(result.errors).toContain(
|
|
127
|
+
"Option 'format' must be one of: json, xml, yaml",
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("should pass validation when no optionDefinitions", () => {
|
|
132
|
+
const parsed: ParsedOptions = { anything: "value" };
|
|
133
|
+
const result = validateOptions(parsed, command);
|
|
134
|
+
expect(result.valid).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("should validate multiple errors at once", () => {
|
|
138
|
+
command.optionDefinitions = [
|
|
139
|
+
{
|
|
140
|
+
name: "port",
|
|
141
|
+
type: "number",
|
|
142
|
+
description: "Port",
|
|
143
|
+
required: true,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "format",
|
|
147
|
+
type: "string",
|
|
148
|
+
description: "Format",
|
|
149
|
+
allowedValues: ["json", "xml"],
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
const parsed: ParsedOptions = { format: "invalid" };
|
|
153
|
+
const result = validateOptions(parsed, command);
|
|
154
|
+
expect(result.valid).toBe(false);
|
|
155
|
+
expect(result.errors.length).toBeGreaterThan(1);
|
|
156
|
+
});
|
|
157
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
"target": "ESNext",
|
|
6
6
|
"module": "ESNext",
|
|
7
7
|
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
8
|
"allowJs": true,
|
|
10
9
|
|
|
11
10
|
// Bundler mode
|
|
@@ -20,8 +19,8 @@
|
|
|
20
19
|
"noFallthroughCasesInSwitch": true,
|
|
21
20
|
|
|
22
21
|
// Some stricter flags (disabled by default)
|
|
23
|
-
"noUnusedLocals":
|
|
24
|
-
"noUnusedParameters":
|
|
22
|
+
"noUnusedLocals": true,
|
|
23
|
+
"noUnusedParameters": true,
|
|
25
24
|
"noPropertyAccessFromIndexSignature": false
|
|
26
25
|
}
|
|
27
26
|
}
|
package/src/example.e2e.test.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, spyOn } from "bun:test";
|
|
2
|
-
|
|
3
|
-
describe("example e2e", () => {
|
|
4
|
-
const { log } = globalThis.console;
|
|
5
|
-
let logs: any[] = [];
|
|
6
|
-
spyOn(globalThis.console, "log").mockImplementation((...args: any) => {
|
|
7
|
-
logs.push(args);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it("should runs ok", (done) => {
|
|
11
|
-
expect(logs).toHaveLength(0);
|
|
12
|
-
//@ts-ignore
|
|
13
|
-
import("./example");
|
|
14
|
-
const check = () => {
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
const { commands } = globalThis;
|
|
17
|
-
if (!commands) return;
|
|
18
|
-
expect(logs).toHaveLength(3);
|
|
19
|
-
expect(logs).toStrictEqual([
|
|
20
|
-
["argument 'asdasd' not defined"],
|
|
21
|
-
["arguments 'pos0value, pos1value, asdasd' not defined"],
|
|
22
|
-
[
|
|
23
|
-
{
|
|
24
|
-
opt1: "qw111erty",
|
|
25
|
-
opt2: "as222d",
|
|
26
|
-
pos0: "pos0value",
|
|
27
|
-
pos1: "pos1value",
|
|
28
|
-
pos3: "asdasd",
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
]);
|
|
32
|
-
clearInterval(handler);
|
|
33
|
-
done();
|
|
34
|
-
};
|
|
35
|
-
const handler = setInterval(check, 10);
|
|
36
|
-
});
|
|
37
|
-
});
|
package/src/example.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { getCommands } from ".";
|
|
2
|
-
import type { Commands } from "./types";
|
|
3
|
-
|
|
4
|
-
const commands = getCommands("test program", "0.0.14")
|
|
5
|
-
.addCommand("com1")
|
|
6
|
-
.addAlias("c1")
|
|
7
|
-
.addOption("opt1")
|
|
8
|
-
.addOption("opt2")
|
|
9
|
-
.addDescription("command 001 test...")
|
|
10
|
-
.addPositionedArgument("pos0")
|
|
11
|
-
.addPositionedArgument("pos1")
|
|
12
|
-
.setCallback(console.log)
|
|
13
|
-
|
|
14
|
-
.commands()
|
|
15
|
-
|
|
16
|
-
.addCommand("com2")
|
|
17
|
-
.addAlias("c2")
|
|
18
|
-
.addAlias("a2")
|
|
19
|
-
.addOption("opt1")
|
|
20
|
-
.addDescription("command 002 test...")
|
|
21
|
-
.setCallback(console.log)
|
|
22
|
-
|
|
23
|
-
.commands()
|
|
24
|
-
|
|
25
|
-
.addCommand("com3")
|
|
26
|
-
.addAlias("c3")
|
|
27
|
-
.addOption("opt1")
|
|
28
|
-
.addOption("opt2", "exOpt2...")
|
|
29
|
-
.addOption("opt3")
|
|
30
|
-
.addDescription("command 003 test...")
|
|
31
|
-
.addPositionedArgument("pos0")
|
|
32
|
-
.addPositionedArgument("pos1")
|
|
33
|
-
.addPositionedArgument("pos3")
|
|
34
|
-
.setCallback(console.log)
|
|
35
|
-
|
|
36
|
-
.commands()
|
|
37
|
-
|
|
38
|
-
.addHeaderText("header...\n\n")
|
|
39
|
-
.addFooterText("\n\nFooter...");
|
|
40
|
-
|
|
41
|
-
commands.start([
|
|
42
|
-
"",
|
|
43
|
-
"",
|
|
44
|
-
..."com1 pos0value opt1=qw111erty pos1value opt2=as222d asdasd"
|
|
45
|
-
.replace(/\s+/g, " ")
|
|
46
|
-
.split(" "),
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
commands.start([
|
|
50
|
-
"",
|
|
51
|
-
"",
|
|
52
|
-
..."a2 pos0value opt1=qw111erty pos1value opt2=as222d asdasd"
|
|
53
|
-
.replace(/\s+/g, " ")
|
|
54
|
-
.split(" "),
|
|
55
|
-
]);
|
|
56
|
-
|
|
57
|
-
commands.start([
|
|
58
|
-
"",
|
|
59
|
-
"",
|
|
60
|
-
..."c3 pos0value opt1=qw111erty pos1value opt2=as222d asdasd"
|
|
61
|
-
.replace(/\s+/g, " ")
|
|
62
|
-
.split(" "),
|
|
63
|
-
]);
|
|
64
|
-
|
|
65
|
-
declare global {
|
|
66
|
-
var commands: Commands;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
globalThis.commands = commands;
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
-
import type { CommandFactory, Commands, CommandsCollection } from "./types";
|
|
3
|
-
import {
|
|
4
|
-
getAddFooterText,
|
|
5
|
-
getAddHeaderText,
|
|
6
|
-
getAddOption,
|
|
7
|
-
getAddPositionedArgument,
|
|
8
|
-
getCommands,
|
|
9
|
-
getGetHelpLine,
|
|
10
|
-
initCommands,
|
|
11
|
-
initHelpAndVersion,
|
|
12
|
-
} from "./getCommandsFuncs";
|
|
13
|
-
|
|
14
|
-
describe("main", () => {
|
|
15
|
-
let commandsCollection: CommandsCollection;
|
|
16
|
-
let commands: Commands;
|
|
17
|
-
let commandFactory: CommandFactory;
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
commandsCollection = {};
|
|
21
|
-
commandFactory = <CommandFactory>(<unknown>{
|
|
22
|
-
commands: undefined,
|
|
23
|
-
name: undefined,
|
|
24
|
-
addAlias: undefined,
|
|
25
|
-
addOption: undefined,
|
|
26
|
-
addPositionedArgument: undefined,
|
|
27
|
-
addDescription: undefined,
|
|
28
|
-
setCallback: undefined,
|
|
29
|
-
});
|
|
30
|
-
commands = initCommands(commandsCollection, undefined, commandFactory);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("getCommands", () => {
|
|
34
|
-
const commands = getCommands();
|
|
35
|
-
expect(commands).toBeTruthy;
|
|
36
|
-
});
|
|
37
|
-
it("initHelpAndVersion", () => {
|
|
38
|
-
expect(commandsCollection).not.toHaveProperty("help");
|
|
39
|
-
expect(commandsCollection).not.toHaveProperty("version");
|
|
40
|
-
const { helpCallback, versionCallback } = initHelpAndVersion(
|
|
41
|
-
commands,
|
|
42
|
-
commandsCollection
|
|
43
|
-
);
|
|
44
|
-
expect(commandsCollection).toHaveProperty("help");
|
|
45
|
-
expect(commandsCollection).toHaveProperty("version");
|
|
46
|
-
|
|
47
|
-
expect(helpCallback).not.toThrow();
|
|
48
|
-
expect(versionCallback).not.toThrow();
|
|
49
|
-
});
|
|
50
|
-
it("getAddOption", () => {
|
|
51
|
-
commands.addCommand("test");
|
|
52
|
-
const addOption = getAddOption(commandFactory, commandsCollection);
|
|
53
|
-
addOption("op001");
|
|
54
|
-
const { test } = commandsCollection;
|
|
55
|
-
expect(test.options.includes("op001"));
|
|
56
|
-
});
|
|
57
|
-
it("getAddPositionedArgument", () => {
|
|
58
|
-
commands.addCommand("test");
|
|
59
|
-
const addPositionedArgument = getAddPositionedArgument(
|
|
60
|
-
commandFactory,
|
|
61
|
-
commandsCollection
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
addPositionedArgument("pos001");
|
|
65
|
-
const { test } = commandsCollection;
|
|
66
|
-
|
|
67
|
-
expect(test.positionedArguments.includes("pos001"));
|
|
68
|
-
});
|
|
69
|
-
it("getAddHeaderText", () => {
|
|
70
|
-
const addHeaderText = getAddHeaderText(commands);
|
|
71
|
-
const txt = "test header text...";
|
|
72
|
-
addHeaderText(txt);
|
|
73
|
-
expect(commands.headerText).toBe(txt);
|
|
74
|
-
});
|
|
75
|
-
it("getAddFooterText", () => {
|
|
76
|
-
const addFooterText = getAddFooterText(commands);
|
|
77
|
-
const txt = "test footer text...";
|
|
78
|
-
addFooterText(txt);
|
|
79
|
-
expect(commands.footerText).toBe(txt);
|
|
80
|
-
});
|
|
81
|
-
it("getGetHelpLine", () => {
|
|
82
|
-
commands.addCommand("test");
|
|
83
|
-
const { test } = commandsCollection;
|
|
84
|
-
const getHelpLine = getGetHelpLine(test);
|
|
85
|
-
const hl50 = getHelpLine();
|
|
86
|
-
expect(hl50).toBe("test ............................................ \n");
|
|
87
|
-
});
|
|
88
|
-
it("", () => {
|
|
89
|
-
commandFactory.commands = <() => Commands>(<unknown>undefined);
|
|
90
|
-
initCommands(commandsCollection, commands, commandFactory);
|
|
91
|
-
expect(commandFactory.commands).toBeTruthy;
|
|
92
|
-
expect(commandFactory.commands).not.toThrow();
|
|
93
|
-
});
|
|
94
|
-
});
|
package/src/getStart.test.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
afterEach,
|
|
3
|
-
beforeEach,
|
|
4
|
-
describe,
|
|
5
|
-
expect,
|
|
6
|
-
it,
|
|
7
|
-
mock,
|
|
8
|
-
spyOn,
|
|
9
|
-
type Mock,
|
|
10
|
-
} from "bun:test";
|
|
11
|
-
|
|
12
|
-
import { getStart } from "./getStart";
|
|
13
|
-
import { commandsCollection } from "./testConstants";
|
|
14
|
-
|
|
15
|
-
describe("getStart", () => {
|
|
16
|
-
let callback: Mock<any>;
|
|
17
|
-
let start: (argv?: string[]) => void;
|
|
18
|
-
let logMock: Mock<any>;
|
|
19
|
-
let logs: any[] = [];
|
|
20
|
-
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
callback = mock();
|
|
23
|
-
commandsCollection.command_1.callback = callback;
|
|
24
|
-
start = getStart(commandsCollection);
|
|
25
|
-
logMock = spyOn(console, "log").mockImplementation((...args: any) => {
|
|
26
|
-
logs.push(args);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
callback.mockClear();
|
|
31
|
-
logMock.mockClear();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("happy path, run command", () => {
|
|
35
|
-
start(["", "", "command_1"]);
|
|
36
|
-
expect(callback).toBeCalledTimes(1);
|
|
37
|
-
});
|
|
38
|
-
it("run command with option", () => {
|
|
39
|
-
start(["", "", "command_1", "op1=value1"]);
|
|
40
|
-
expect(callback).toBeCalledTimes(1);
|
|
41
|
-
});
|
|
42
|
-
it("run command with extra positioned arguments", () => {
|
|
43
|
-
logs = [];
|
|
44
|
-
start(["", "", "command_1", "pos1", "pos2", "pos3"]);
|
|
45
|
-
start(["", "", "command_1", "pos1", "pos2", "pos3", "pos4"]);
|
|
46
|
-
expect(logs).toHaveLength(2);
|
|
47
|
-
expect(logs[0]).toHaveLength(1);
|
|
48
|
-
expect(logs[0][0]).toBe("argument 'pos3' not defined");
|
|
49
|
-
expect(logs[1]).toHaveLength(1);
|
|
50
|
-
expect(logs[1][0]).toBe("arguments 'pos3, pos4' not defined");
|
|
51
|
-
});
|
|
52
|
-
it("run with process.argv", () => {
|
|
53
|
-
process.argv = ["", ""];
|
|
54
|
-
start();
|
|
55
|
-
logs = [];
|
|
56
|
-
commandsCollection.help.callback();
|
|
57
|
-
expect(logs).toHaveLength(1);
|
|
58
|
-
});
|
|
59
|
-
it("should throw when no args passed", () => {
|
|
60
|
-
process.argv = <string[]>(<unknown>undefined);
|
|
61
|
-
expect(start).toThrow(new Error("no arguments passed"));
|
|
62
|
-
});
|
|
63
|
-
it("should throw when less than 2 args passed", () => {
|
|
64
|
-
process.argv = [];
|
|
65
|
-
expect(start).toThrow(new Error("arguments out of range"));
|
|
66
|
-
});
|
|
67
|
-
it("should show message when passed an unexistent commnad", () => {
|
|
68
|
-
process.argv = ["", "", "fakeCommand"];
|
|
69
|
-
logs = [];
|
|
70
|
-
start();
|
|
71
|
-
expect(logs).toHaveLength(1);
|
|
72
|
-
expect(logs[0]).toHaveLength(1);
|
|
73
|
-
expect(logs[0][0]).toBe("command 'fakeCommand' not found");
|
|
74
|
-
});
|
|
75
|
-
it("run with less positioned arguments", () => {
|
|
76
|
-
start(["", "", "al1", "arg001"]);
|
|
77
|
-
expect(callback).toBeCalledWith({ pos1: "arg001" });
|
|
78
|
-
});
|
|
79
|
-
});
|
package/src/textFuncs.test.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { command, commands, commandsCollection } from "./testConstants";
|
|
2
|
-
import {
|
|
3
|
-
buildDescriptionsText,
|
|
4
|
-
buildHelpText,
|
|
5
|
-
getCommandText,
|
|
6
|
-
} from "./textFuncs";
|
|
7
|
-
import { describe, expect, it } from "bun:test";
|
|
8
|
-
|
|
9
|
-
describe("text Functions", () => {
|
|
10
|
-
describe("getCommandText", () => {
|
|
11
|
-
it("should return command text", () => {
|
|
12
|
-
const result = getCommandText(command);
|
|
13
|
-
|
|
14
|
-
expect(result).toBe(
|
|
15
|
-
"command_1|al1|al2 [pos1] [pos2] [op1=opEx1] [op2=VALUE] "
|
|
16
|
-
);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("should return command text without aliases", () => {
|
|
20
|
-
const result = getCommandText({ ...command, aliases: [] });
|
|
21
|
-
|
|
22
|
-
expect(result).toBe(
|
|
23
|
-
"command_1 [pos1] [pos2] [op1=opEx1] [op2=VALUE] "
|
|
24
|
-
);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
describe("buildHelpText", () => {
|
|
28
|
-
it("should return help text", () => {
|
|
29
|
-
const result = buildHelpText(commands, commandsCollection);
|
|
30
|
-
expect(result).toBe(
|
|
31
|
-
"\nheader text...\nhelp line...\nhelp line...\nhelp line...\nfooter text...\n"
|
|
32
|
-
);
|
|
33
|
-
});
|
|
34
|
-
it("should return help text without headerText", () => {
|
|
35
|
-
const result = buildHelpText(
|
|
36
|
-
{ ...commands, headerText: "" },
|
|
37
|
-
commandsCollection
|
|
38
|
-
);
|
|
39
|
-
expect(result).toBe(
|
|
40
|
-
"\n\nhelp line...\nhelp line...\nhelp line...\nfooter text...\n"
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
it("should return help text without footerText", () => {
|
|
44
|
-
const result = buildHelpText(
|
|
45
|
-
{ ...commands, footerText: "" },
|
|
46
|
-
commandsCollection
|
|
47
|
-
);
|
|
48
|
-
expect(result).toBe(
|
|
49
|
-
"\nheader text...\nhelp line...\nhelp line...\nhelp line...\n\n"
|
|
50
|
-
);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
describe("buildDescriptionsText", () => {
|
|
54
|
-
it("should return description text", () => {
|
|
55
|
-
const result = buildDescriptionsText(commandsCollection);
|
|
56
|
-
expect(result).toBe("help line...\n".repeat(3));
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
});
|