Skip to content

Commit f950f42

Browse files
committed
feat: [Command] configure help subcommand to print help text
Signed-off-by: Lexus Drumgold <[email protected]>
1 parent 4e593aa commit f950f42

File tree

6 files changed

+142
-24
lines changed

6 files changed

+142
-24
lines changed

src/lib/__snapshots__/command.functional.snap

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,27 @@ exports[`functional:lib/Command > parsing > should run command (11) 1`] = `
13521352
`;
13531353

13541354
exports[`functional:lib/Command > parsing > should run command (12) 1`] = `
1355+
{
1356+
"command": "help",
1357+
"ancestors": [
1358+
"grease",
1359+
],
1360+
"args": [],
1361+
"argv": [],
1362+
"optionValueSources": {},
1363+
"opts": {},
1364+
"optsWithGlobals": {
1365+
"config": true,
1366+
"level": "info",
1367+
"tagPrefix": "",
1368+
"write": false,
1369+
"color": true,
1370+
"cwd": "\${process.cwd()}",
1371+
},
1372+
}
1373+
`;
1374+
1375+
exports[`functional:lib/Command > parsing > should run command (13) 1`] = `
13551376
{
13561377
"command": "bump",
13571378
"ancestors": [
@@ -1380,7 +1401,30 @@ exports[`functional:lib/Command > parsing > should run command (12) 1`] = `
13801401
}
13811402
`;
13821403

1383-
exports[`functional:lib/Command > parsing > should run command (13) 1`] = `
1404+
exports[`functional:lib/Command > parsing > should run command (14) 1`] = `
1405+
{
1406+
"command": "help",
1407+
"ancestors": [
1408+
"bump",
1409+
"grease",
1410+
],
1411+
"args": [],
1412+
"argv": [],
1413+
"optionValueSources": {},
1414+
"opts": {},
1415+
"optsWithGlobals": {
1416+
"config": true,
1417+
"level": "info",
1418+
"tagPrefix": "",
1419+
"write": false,
1420+
"color": true,
1421+
"cwd": "\${process.cwd()}",
1422+
"prestart": 1,
1423+
},
1424+
}
1425+
`;
1426+
1427+
exports[`functional:lib/Command > parsing > should run command (15) 1`] = `
13841428
{
13851429
"command": "grease",
13861430
"ancestors": [],
@@ -1419,7 +1463,7 @@ exports[`functional:lib/Command > parsing > should run command (13) 1`] = `
14191463
}
14201464
`;
14211465

1422-
exports[`functional:lib/Command > parsing > should run command (14) 1`] = `
1466+
exports[`functional:lib/Command > parsing > should run command (16) 1`] = `
14231467
{
14241468
"command": "recommend",
14251469
"ancestors": [
@@ -1445,7 +1489,7 @@ exports[`functional:lib/Command > parsing > should run command (14) 1`] = `
14451489
}
14461490
`;
14471491

1448-
exports[`functional:lib/Command > parsing > should run command (15) 1`] = `
1492+
exports[`functional:lib/Command > parsing > should run command (17) 1`] = `
14491493
{
14501494
"command": "changelog",
14511495
"ancestors": [
@@ -1477,7 +1521,7 @@ exports[`functional:lib/Command > parsing > should run command (15) 1`] = `
14771521
}
14781522
`;
14791523

1480-
exports[`functional:lib/Command > parsing > should run command (16) 1`] = `
1524+
exports[`functional:lib/Command > parsing > should run command (18) 1`] = `
14811525
{
14821526
"command": "changelog",
14831527
"ancestors": [
@@ -1512,7 +1556,7 @@ exports[`functional:lib/Command > parsing > should run command (16) 1`] = `
15121556
}
15131557
`;
15141558

1515-
exports[`functional:lib/Command > parsing > should run command (17) 1`] = `
1559+
exports[`functional:lib/Command > parsing > should run command (19) 1`] = `
15161560
{
15171561
"command": "pack",
15181562
"ancestors": [
@@ -1541,7 +1585,7 @@ exports[`functional:lib/Command > parsing > should run command (17) 1`] = `
15411585
}
15421586
`;
15431587

1544-
exports[`functional:lib/Command > parsing > should run command (18) 1`] = `
1588+
exports[`functional:lib/Command > parsing > should run command (20) 1`] = `
15451589
{
15461590
"command": "create",
15471591
"ancestors": [
@@ -1585,7 +1629,7 @@ exports[`functional:lib/Command > parsing > should run command (18) 1`] = `
15851629
}
15861630
`;
15871631

1588-
exports[`functional:lib/Command > parsing > should run command (19) 1`] = `
1632+
exports[`functional:lib/Command > parsing > should run command (21) 1`] = `
15891633
{
15901634
"command": "mlly",
15911635
"ancestors": [],
@@ -1606,7 +1650,7 @@ exports[`functional:lib/Command > parsing > should run command (19) 1`] = `
16061650
}
16071651
`;
16081652

1609-
exports[`functional:lib/Command > parsing > should run command (20) 1`] = `
1653+
exports[`functional:lib/Command > parsing > should run command (22) 1`] = `
16101654
{
16111655
"command": "resolve",
16121656
"ancestors": [
@@ -1639,7 +1683,7 @@ exports[`functional:lib/Command > parsing > should run command (20) 1`] = `
16391683
}
16401684
`;
16411685

1642-
exports[`functional:lib/Command > parsing > should run command (21) 1`] = `
1686+
exports[`functional:lib/Command > parsing > should run command (23) 1`] = `
16431687
{
16441688
"command": "resolve",
16451689
"ancestors": [
@@ -1674,7 +1718,7 @@ exports[`functional:lib/Command > parsing > should run command (21) 1`] = `
16741718
}
16751719
`;
16761720

1677-
exports[`functional:lib/Command > parsing > should run command (22) 1`] = `
1721+
exports[`functional:lib/Command > parsing > should run command (24) 1`] = `
16781722
{
16791723
"command": "resolve",
16801724
"ancestors": [
@@ -1711,7 +1755,7 @@ exports[`functional:lib/Command > parsing > should run command (22) 1`] = `
17111755
}
17121756
`;
17131757

1714-
exports[`functional:lib/Command > parsing > should run command (23) 1`] = `
1758+
exports[`functional:lib/Command > parsing > should run command (25) 1`] = `
17151759
{
17161760
"command": "smallest-num",
17171761
"ancestors": [],
@@ -1734,7 +1778,7 @@ exports[`functional:lib/Command > parsing > should run command (23) 1`] = `
17341778
}
17351779
`;
17361780

1737-
exports[`functional:lib/Command > parsing > should run command (24) 1`] = `
1781+
exports[`functional:lib/Command > parsing > should run command (26) 1`] = `
17381782
{
17391783
"command": "join",
17401784
"ancestors": [
@@ -1754,7 +1798,7 @@ exports[`functional:lib/Command > parsing > should run command (24) 1`] = `
17541798
}
17551799
`;
17561800

1757-
exports[`functional:lib/Command > parsing > should run command (25) 1`] = `
1801+
exports[`functional:lib/Command > parsing > should run command (27) 1`] = `
17581802
{
17591803
"command": "tribonacci",
17601804
"ancestors": [],

src/lib/__snapshots__/command.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ Command {
133133
},
134134
"subcommands": Map {},
135135
"version": undefined,
136-
"action": undefined,
136+
"action": [Function bound help],
137137
"done": undefined,
138138
"exit": undefined,
139139
"optionPriority": "local",

src/lib/__tests__/command.functional.spec.mts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ describe('functional:lib/Command', () => {
288288
let process: Process
289289
let log: MockInstance<Logger['log']>
290290
let message: string | undefined
291-
let subcommand: TestSubject | undefined
291+
let subcommand: TestSubject | null | undefined
292292

293293
afterEach(() => {
294294
action = undefined
@@ -387,6 +387,32 @@ describe('functional:lib/Command', () => {
387387
}
388388
}
389389
],
390+
[
391+
Object.assign({}, grease, { help: true as const }),
392+
['help'],
393+
/**
394+
* @this {void}
395+
*
396+
* @return {ParseCaseHooks}
397+
* Test case hooks
398+
*/
399+
function context(this: void): ParseCaseHooks {
400+
return {
401+
/**
402+
* @this {void}
403+
*
404+
* @param {TestSubject} subject
405+
* The command under test
406+
* @return {undefined}
407+
*/
408+
before(this: void, subject: TestSubject): undefined {
409+
subcommand = subject.helpCommand()
410+
ok(subcommand, 'expected `subcommand`')
411+
return message = '', void this
412+
}
413+
}
414+
}
415+
],
390416
[
391417
Object.assign({}, grease, { actionOverride: true as const }),
392418
[grease.name, 'bump', '-h'],
@@ -415,6 +441,36 @@ describe('functional:lib/Command', () => {
415441
}
416442
}
417443
],
444+
[
445+
Object.assign({}, grease, { help: true as const }),
446+
[grease.name, 'bump', 'help'],
447+
/**
448+
* @this {void}
449+
*
450+
* @param {string[]} argv
451+
* Command-line arguments
452+
* @return {ParseCaseHooks}
453+
* Test case hooks
454+
*/
455+
function context(this: void, argv: string[]): ParseCaseHooks {
456+
return {
457+
/**
458+
* @this {void}
459+
*
460+
* @param {TestSubject} subject
461+
* The command under test
462+
* @return {undefined}
463+
*/
464+
before(this: void, subject: TestSubject): undefined {
465+
subcommand = subject.commands().get(argv[1]!)!
466+
ok(subcommand, 'expected `subcommand`')
467+
subcommand = subcommand.helpCommand()
468+
ok(subcommand, 'expected `subcommand`')
469+
return message = '', void this
470+
}
471+
}
472+
}
473+
],
418474
[
419475
Object.assign({}, grease, { actionOverride: true as const }),
420476
['-u', '--version'],
@@ -774,6 +830,12 @@ describe('functional:lib/Command', () => {
774830
if (info.actionOverride) {
775831
expect(action).not.toHaveBeenCalled()
776832
expect(log).toHaveBeenCalledExactlyOnceWith(message)
833+
expect(done).toHaveBeenCalledAfter(log)
834+
} else if (info.help) {
835+
expect(action).toHaveBeenCalledOnce()
836+
expect(action.mock.contexts[0]).to.eq(result)
837+
expect(action.mock.lastCall).to.eql([opts, ...result.args])
838+
expect(done).toHaveBeenCalledAfter(action)
777839
} else {
778840
expect(action).toHaveBeenCalledOnce()
779841
expect(action.mock.contexts[0]).to.eq(result)

src/lib/__tests__/command.spec.mts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ describe('unit:lib/Command', () => {
435435
it.each<[HelpCommandData]>([
436436
[false],
437437
['more'],
438-
[new TestSubject('info')],
438+
[new TestSubject('info', { action: vi.fn() })],
439439
[{ description: 'show help for command', name: 'details' }]
440440
])('should set help subcommand and return `this` (%#)', help => {
441441
// Arrange
@@ -453,6 +453,7 @@ describe('unit:lib/Command', () => {
453453
expect(result).to.have.nested.property(prop, null)
454454
} else if (TestSubject.isCommand(help)) {
455455
expect(result).to.have.nested.property(prop, help)
456+
expect(help).to.have.nested.property('info.action.mock')
456457
} else {
457458
expect(result).to.have.nested.property(prop).not.eq(help)
458459
expect(result).to.have.nested.property(prop).be.instanceof(TestSubject)

src/lib/command.mts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,12 +2142,10 @@ class Command extends Helpable {
21422142
* @public
21432143
* @instance
21442144
*
2145-
* @return {this}
2146-
* `this` command
2145+
* @return {undefined}
21472146
*/
2148-
public help(): this {
2149-
this.logger.log('')
2150-
return this
2147+
public help(): undefined {
2148+
return void this.logger.log('')
21512149
}
21522150

21532151
/**
@@ -2189,8 +2187,6 @@ class Command extends Helpable {
21892187
/**
21902188
* Get or configure the help subcommand.
21912189
*
2192-
* @todo configure subcommand to print help text
2193-
*
21942190
* @see {@linkcode Command}
21952191
* @see {@linkcode HelpCommandData}
21962192
*
@@ -2219,7 +2215,15 @@ class Command extends Helpable {
22192215
: this
22202216
// prevent `RangeError: Maximum call stack size exceeded`
22212217
// by disabling help subcommand for current help subcommand.
2222-
.command({ ...help, helpCommand: false })
2218+
.createCommand({ ...help, helpCommand: false })
2219+
2220+
// add help subcommand.
2221+
this.addCommand(this.info.helpCommand)
2222+
2223+
// configure help subcommand to print help text.
2224+
if (this.info.helpCommand.action() === noop) {
2225+
this.info.helpCommand.action(this.help.bind(this))
2226+
}
22232227
}
22242228

22252229
return this

typings/@flex-development/kronk/index.d.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ declare module '@flex-development/kronk' {
2828
* @internal
2929
*/
3030
async?: true
31+
32+
/**
33+
* Whether help text is expected to be printed during testing.
34+
*
35+
* @internal
36+
*/
37+
help?: true
3138
}
3239
}
3340

0 commit comments

Comments
 (0)