@neurodevs/ndx-cli 0.1.54 → 0.1.57

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.
Files changed (37) hide show
  1. package/build/__tests__/AbstractCommandRunnerTest.d.ts +66 -0
  2. package/build/__tests__/AbstractCommandRunnerTest.js +264 -0
  3. package/build/__tests__/AbstractCommandRunnerTest.js.map +1 -0
  4. package/build/__tests__/modules/CliCommandRunner.test.d.ts +2 -94
  5. package/build/__tests__/modules/CliCommandRunner.test.js +2 -675
  6. package/build/__tests__/modules/CliCommandRunner.test.js.map +1 -1
  7. package/build/__tests__/modules/commands/BindSnippetCommand.test.d.ts +20 -0
  8. package/build/__tests__/modules/commands/BindSnippetCommand.test.js +111 -0
  9. package/build/__tests__/modules/commands/BindSnippetCommand.test.js.map +1 -0
  10. package/build/__tests__/modules/commands/CreateImplCommand.test.d.ts +13 -0
  11. package/build/__tests__/modules/commands/CreateImplCommand.test.js +112 -0
  12. package/build/__tests__/modules/commands/CreateImplCommand.test.js.map +1 -0
  13. package/build/__tests__/modules/commands/CreatePackageCommand.test.d.ts +10 -0
  14. package/build/__tests__/modules/commands/CreatePackageCommand.test.js +98 -0
  15. package/build/__tests__/modules/commands/CreatePackageCommand.test.js.map +1 -0
  16. package/build/__tests__/modules/commands/CreateUiCommand.test.d.ts +22 -0
  17. package/build/__tests__/modules/commands/CreateUiCommand.test.js +220 -0
  18. package/build/__tests__/modules/commands/CreateUiCommand.test.js.map +1 -0
  19. package/build/__tests__/modules/commands/UpgradePackageCommand.test.d.ts +11 -0
  20. package/build/__tests__/modules/commands/UpgradePackageCommand.test.js +90 -0
  21. package/build/__tests__/modules/commands/UpgradePackageCommand.test.js.map +1 -0
  22. package/build/modules/CliCommandRunner.d.ts +4 -2
  23. package/build/modules/CliCommandRunner.js +18 -7
  24. package/build/modules/CliCommandRunner.js.map +1 -1
  25. package/build/modules/commands/BindSnippetCommand.d.ts +16 -0
  26. package/build/modules/commands/BindSnippetCommand.js +67 -0
  27. package/build/modules/commands/BindSnippetCommand.js.map +1 -0
  28. package/package.json +3 -2
  29. package/src/__tests__/AbstractCommandRunnerTest.ts +321 -0
  30. package/src/__tests__/modules/CliCommandRunner.test.ts +3 -910
  31. package/src/__tests__/modules/commands/BindSnippetCommand.test.ts +129 -0
  32. package/src/__tests__/modules/commands/CreateImplCommand.test.ts +137 -0
  33. package/src/__tests__/modules/commands/CreatePackageCommand.test.ts +113 -0
  34. package/src/__tests__/modules/commands/CreateUiCommand.test.ts +297 -0
  35. package/src/__tests__/modules/commands/UpgradePackageCommand.test.ts +105 -0
  36. package/src/modules/CliCommandRunner.ts +19 -7
  37. package/src/modules/commands/BindSnippetCommand.ts +75 -0
@@ -1,81 +1,11 @@
1
- import { exec as execSync } from 'child_process'
2
- import { mkdir, readFile, writeFile } from 'fs/promises'
3
- import os from 'os'
4
- import path from 'path'
5
- import { promisify } from 'util'
6
1
  import { test, assert, generateId } from '@sprucelabs/test-utils'
7
- import {
8
- callsToExec,
9
- callsToLog,
10
- callsToMkdir,
11
- callsToWriteFile,
12
- fakeExec,
13
- fakeLog,
14
- fakeMkdir,
15
- fakeReadFile,
16
- fakeWriteFile,
17
- resetCallsToExec,
18
- resetCallsToLog,
19
- resetCallsToMkdir,
20
- resetCallsToReadFile,
21
- resetCallsToWriteFile,
22
- setFakeReadFileResult,
23
- } from '@neurodevs/fake-node-core'
24
- import {
25
- FakeAutomodule,
26
- FakeAutopackage,
27
- ImplAutomodule,
28
- NpmAutopackage,
29
- UiAutomodule,
30
- } from '@neurodevs/meta-node'
31
- import prompts from 'prompts'
32
- import CliCommandRunner from '../../modules/CliCommandRunner'
33
- import fakePrompts, {
34
- callsToFakePrompts,
35
- resetCallsToFakePrompts,
36
- setFakeResponses,
37
- } from '../../testDoubles/prompts/fakePrompts'
38
- import AbstractPackageTest from '../AbstractPackageTest'
2
+ import { callsToLog } from '@neurodevs/fake-node-core'
39
3
 
40
- const exec = promisify(execSync)
41
-
42
- export default class CliCommandRunnerTest extends AbstractPackageTest {
43
- private static readonly createImplCommand = 'create.impl'
44
- private static readonly interfaceName = generateId()
45
- private static readonly implName = generateId()
46
-
47
- private static readonly createPackageCommand = 'create.package'
48
- private static readonly packageName = generateId()
49
- private static readonly description = generateId()
50
- private static readonly keywords = [generateId(), generateId()]
51
- private static readonly githubToken = generateId()
52
-
53
- private static readonly defaultKeywords = ['nodejs', 'typescript', 'tdd']
54
-
55
- private static get keywordsWithDefaults() {
56
- return [...this.defaultKeywords, ...this.keywords]
57
- }
58
-
59
- private static readonly createUiCommand = 'create.ui'
60
- private static readonly componentName = generateId()
61
-
62
- private static readonly upgradePackageCommand = 'upgrade.package'
4
+ import AbstractCommandRunnerTest from '../AbstractCommandRunnerTest'
63
5
 
6
+ export default class CliCommandRunnerTest extends AbstractCommandRunnerTest {
64
7
  protected static async beforeEach() {
65
8
  await super.beforeEach()
66
-
67
- this.setFakeImplAutomodule()
68
- this.setFakeUiAutomodule()
69
- this.setFakeAutopackage()
70
-
71
- this.setFakeExec()
72
- this.setFakeLog()
73
- this.setFakeMkdir()
74
- this.setFakePrompts()
75
- this.setFakeReadFile()
76
- this.setFakeWriteFile()
77
-
78
- process.env.GITHUB_TOKEN = this.githubToken
79
9
  }
80
10
 
81
11
  @test()
@@ -94,468 +24,6 @@ export default class CliCommandRunnerTest extends AbstractPackageTest {
94
24
  )
95
25
  }
96
26
 
97
- @test()
98
- protected static async createImplCreatesInstance() {
99
- const instance = await this.runCreateImpl()
100
-
101
- assert.isTruthy(
102
- instance,
103
- `Failed to create instance for ${this.createImplCommand}!`
104
- )
105
- }
106
-
107
- @test()
108
- protected static async createImplPromptsUserForInput() {
109
- await this.runCreateImpl()
110
-
111
- assert.isEqualDeep(
112
- callsToFakePrompts[0],
113
- [
114
- {
115
- type: 'text',
116
- name: 'interfaceName',
117
- message: this.interfaceNameMessage,
118
- },
119
- {
120
- type: 'text',
121
- name: 'implName',
122
- message: this.implNameMessage,
123
- },
124
- ],
125
- 'Did not prompt user for expected input!'
126
- )
127
- }
128
-
129
- @test()
130
- protected static async createImplDoesNotContinueIfPromptsIsInterrupted() {
131
- await this.runCreateImpl({
132
- interfaceName: '',
133
- implName: '',
134
- })
135
-
136
- assert.isEqual(
137
- FakeAutomodule.numCallsToRun,
138
- 0,
139
- 'Should not have called run on ImplAutomodule!'
140
- )
141
- }
142
-
143
- @test()
144
- protected static async createImplCreatesTestSaveDirIfNotExists() {
145
- await this.runCreateImpl()
146
-
147
- assert.isEqualDeep(
148
- callsToMkdir[0],
149
- { path: this.implTestSaveDir, options: { recursive: true } },
150
- 'Did not create test save dir!'
151
- )
152
- }
153
-
154
- @test()
155
- protected static async createImplCreatesModuleSaveDirIfNotExists() {
156
- await this.runCreateImpl()
157
-
158
- assert.isEqualDeep(
159
- callsToMkdir[1],
160
- { path: this.implModuleSaveDir, options: { recursive: true } },
161
- 'Did not create module save dir!'
162
- )
163
- }
164
-
165
- @test()
166
- protected static async createImplCreatesFakeSaveDirIfNotExists() {
167
- await this.runCreateImpl()
168
-
169
- assert.isEqualDeep(
170
- callsToMkdir[2],
171
- {
172
- path: `src/testDoubles/${this.interfaceName}`,
173
- options: { recursive: true },
174
- },
175
- 'Did not create fake save dir!'
176
- )
177
- }
178
-
179
- @test()
180
- protected static async createImplCreatesImplAutomodule() {
181
- await this.runCreateImpl()
182
-
183
- assert.isEqualDeep(
184
- FakeAutomodule.callsToConstructor[0],
185
- {
186
- testSaveDir: this.implTestSaveDir,
187
- moduleSaveDir: this.implModuleSaveDir,
188
- fakeSaveDir: this.implFakeSaveDir,
189
- interfaceName: this.interfaceName,
190
- implName: this.implName,
191
- },
192
- 'Did not create ImplAutomodule with expected options!'
193
- )
194
- }
195
-
196
- @test()
197
- protected static async createImplRunsImplAutomodule() {
198
- await this.runCreateImpl()
199
-
200
- assert.isEqual(
201
- FakeAutomodule.numCallsToRun,
202
- 1,
203
- 'Did not call run on ImplAutomodule!'
204
- )
205
- }
206
-
207
- @test()
208
- protected static async createPackageCreatesInstance() {
209
- const instance = await this.runCreatePackage()
210
-
211
- assert.isTruthy(
212
- instance,
213
- `Failed to create instance for ${this.createPackageCommand}!`
214
- )
215
- }
216
-
217
- @test()
218
- protected static async createPackagePromptsUserForInput() {
219
- await this.runCreatePackage()
220
-
221
- assert.isEqualDeep(
222
- JSON.stringify(callsToFakePrompts[0]),
223
- JSON.stringify([
224
- {
225
- type: 'text',
226
- name: 'packageName',
227
- message: this.packageNameMessage,
228
- },
229
- {
230
- type: 'text',
231
- name: 'description',
232
- message: this.packageDescriptionMessage,
233
- },
234
- {
235
- type: 'text',
236
- name: 'keywords',
237
- message:
238
- 'Enter keywords (comma or space separated, lowercase, optional):',
239
- initial: '',
240
- format: (value: string) =>
241
- value ? this.splitOnCommaOrWhitespace(value) : [],
242
- },
243
- ]),
244
- 'Did not prompt user for expected input!'
245
- )
246
- }
247
-
248
- @test()
249
- protected static async createPackageDoesNotContinueIfPromptsIsInterrupted() {
250
- await this.runCreatePackage({
251
- packageName: '',
252
- description: '',
253
- })
254
-
255
- assert.isEqual(
256
- FakeAutopackage.numCallsToRun,
257
- 0,
258
- 'Should not have called run on Autopackage!'
259
- )
260
- }
261
-
262
- @test()
263
- protected static async createPackageCreatesNpmAutopackage() {
264
- await this.runCreatePackage()
265
-
266
- assert.isEqualDeep(
267
- FakeAutopackage.callsToConstructor[0],
268
- {
269
- name: this.packageName,
270
- description: this.description,
271
- keywords: this.keywordsWithDefaults,
272
- gitNamespace: 'neurodevs',
273
- npmNamespace: 'neurodevs',
274
- installDir: this.expandHomeDir('~/dev'),
275
- license: 'MIT',
276
- author: 'Eric Yates <hello@ericthecurious.com>',
277
- },
278
- 'Did not create NpmAutopackage with expected options!'
279
- )
280
- }
281
-
282
- @test()
283
- protected static async createPackageRunsNpmAutopackage() {
284
- await this.runCreatePackage()
285
-
286
- assert.isEqual(
287
- FakeAutopackage.numCallsToRun,
288
- 1,
289
- 'Did not call run on NpmAutopackage!'
290
- )
291
- }
292
-
293
- @test()
294
- protected static async createUiCreatesInstance() {
295
- const instance = await this.runCreateUi()
296
-
297
- assert.isTruthy(
298
- instance,
299
- `Failed to create instance for ${this.createUiCommand}!`
300
- )
301
- }
302
-
303
- @test()
304
- protected static async createUiPromptsInstallDependenciesIfMissing() {
305
- this.setFakeReadToEmptyPackageJson()
306
-
307
- await this.runCreateUi()
308
-
309
- assert.isEqualDeep(
310
- callsToFakePrompts[0],
311
- [
312
- {
313
- type: 'confirm',
314
- name: 'shouldInstall',
315
- message:
316
- 'Some required dependencies are missing! Press Enter to install, or any other key to abort.',
317
- initial: true,
318
- },
319
- ],
320
- 'Did not prompt user for expected input!'
321
- )
322
- }
323
-
324
- @test()
325
- protected static async createUiInstallsDependenciesIfMissing() {
326
- this.setFakeReadToEmptyPackageJson()
327
-
328
- await this.runCreateUi({
329
- shouldInstall: true,
330
- })
331
-
332
- assert.isEqualDeep(
333
- callsToExec[0],
334
- this.installDependenciesCommand,
335
- 'Did not install dependencies!'
336
- )
337
- }
338
-
339
- @test()
340
- protected static async createUiInstallsDevDependenciesIfMissing() {
341
- this.setFakeReadToEmptyPackageJson()
342
-
343
- await this.runCreateUi({
344
- shouldInstall: true,
345
- })
346
-
347
- assert.isEqualDeep(
348
- callsToExec[1],
349
- this.installDevDependenciesCommand,
350
- 'Did not install dependencies!'
351
- )
352
- }
353
-
354
- @test()
355
- protected static async createUiInstallsIfAnyDepIsMissing() {
356
- for (const dep of this.allRequiredDependencies) {
357
- this.setFakeReadToAllInstalledExcept(dep)
358
- resetCallsToExec()
359
-
360
- await this.runCreateUi({
361
- shouldInstall: true,
362
- })
363
-
364
- assert.isEqual(
365
- callsToExec[1],
366
- this.installDevDependenciesCommand,
367
- 'Should not have installed devDependencies!'
368
- )
369
- }
370
- }
371
-
372
- @test()
373
- protected static async createUiUpdatesTsconfigIfDepsWereMissing() {
374
- this.setFakeReadToEmptyPackageJson()
375
- this.setFakeReadFileResultToTsconfig()
376
-
377
- await this.runCreateUi({
378
- shouldInstall: true,
379
- })
380
-
381
- assert.isEqualDeep(
382
- callsToWriteFile[0],
383
- {
384
- file: this.tsconfigPath,
385
- data: this.updatedTsconfigFile,
386
- options: undefined,
387
- },
388
- 'Did not update tsconfig!'
389
- )
390
- }
391
-
392
- @test()
393
- protected static async createUiCreatesSetupTestsIfDepsWereMissing() {
394
- this.setFakeReadToEmptyPackageJson()
395
-
396
- await this.runCreateUi({
397
- shouldInstall: true,
398
- })
399
-
400
- assert.isEqualDeep(
401
- callsToWriteFile[1],
402
- {
403
- file: 'src/__tests__/setupTests.ts',
404
- data: this.setupTestsFile,
405
- options: undefined,
406
- },
407
- 'Did not create setupTests script!'
408
- )
409
- }
410
-
411
- @test()
412
- protected static async createUiAddsSetupTestsToPackageJsonIfDepsWereMissing() {
413
- this.setFakeReadToEmptyPackageJson()
414
-
415
- await this.runCreateUi({
416
- shouldInstall: true,
417
- })
418
-
419
- assert.isEqualDeep(
420
- callsToWriteFile[2],
421
- {
422
- file: 'package.json',
423
- data: JSON.stringify(
424
- {
425
- jest: {
426
- setupFiles: [
427
- '<rootDir>/build/__tests__/setupTests.js',
428
- ],
429
- },
430
- },
431
- null,
432
- 4
433
- ),
434
- options: undefined,
435
- },
436
- 'Did not update package.json!'
437
- )
438
- }
439
-
440
- @test()
441
- protected static async createUiRecompilesTypescriptIfDepsWereMissing() {
442
- this.setFakeReadToEmptyPackageJson()
443
-
444
- await this.runCreateUi({
445
- shouldInstall: true,
446
- })
447
-
448
- assert.isEqualDeep(
449
- callsToExec[2],
450
- 'npx tsc',
451
- 'Did not recompile typescript!'
452
- )
453
- }
454
-
455
- @test()
456
- protected static async createUiDoesNotPromptIfDependenciesAreInstalled() {
457
- this.setFakeReadToAllInstalled()
458
-
459
- await this.runCreateUi()
460
-
461
- assert.isEqual(callsToFakePrompts.length, 1, 'Prompted too many times!')
462
- }
463
-
464
- @test()
465
- protected static async createUiPromptsUserForInput() {
466
- this.setFakeReadToAllInstalled()
467
-
468
- await this.runCreateUi()
469
-
470
- assert.isEqualDeep(
471
- callsToFakePrompts[0],
472
- [
473
- {
474
- type: 'text',
475
- name: 'componentName',
476
- message: this.componentNameMessage,
477
- },
478
- ],
479
- 'Did not prompt user for expected input!'
480
- )
481
- }
482
-
483
- @test()
484
- protected static async createUiDoesNotContinueIfPromptsIsInterrupted() {
485
- await this.runCreateUi({
486
- componentName: '',
487
- })
488
-
489
- assert.isEqual(
490
- FakeAutomodule.numCallsToRun,
491
- 0,
492
- 'Should not have called run on UiAutomodule!'
493
- )
494
- }
495
-
496
- @test()
497
- protected static async createUiCreatesTestSaveDirIfNotExists() {
498
- await this.runCreateUi()
499
-
500
- assert.isEqualDeep(
501
- callsToMkdir[0],
502
- { path: this.uiTestSaveDir, options: { recursive: true } },
503
- 'Did not create test save dir!'
504
- )
505
- }
506
-
507
- @test()
508
- protected static async createUiCreatesModuleSaveDirIfNotExists() {
509
- await this.runCreateUi()
510
-
511
- assert.isEqualDeep(
512
- callsToMkdir[1],
513
- { path: this.uiModuleSaveDir, options: { recursive: true } },
514
- 'Did not create module save dir!'
515
- )
516
- }
517
-
518
- @test()
519
- protected static async createUiCreatesFakeSaveDirIfNotExists() {
520
- await this.runCreateUi()
521
-
522
- assert.isEqualDeep(
523
- callsToMkdir[2],
524
- {
525
- path: this.uiFakeSaveDir,
526
- options: { recursive: true },
527
- },
528
- 'Did not create fake save dir!'
529
- )
530
- }
531
-
532
- @test()
533
- protected static async createUiCreatesUiAutomodule() {
534
- await this.runCreateUi()
535
-
536
- assert.isEqualDeep(
537
- FakeAutomodule.callsToConstructor[0],
538
- {
539
- testSaveDir: this.uiTestSaveDir,
540
- moduleSaveDir: this.uiModuleSaveDir,
541
- fakeSaveDir: this.uiFakeSaveDir,
542
- componentName: this.componentName,
543
- },
544
- 'Did not create UiAutomodule with expected options!'
545
- )
546
- }
547
-
548
- @test()
549
- protected static async createUiRunsUiAutomodule() {
550
- await this.runCreateUi()
551
-
552
- assert.isEqual(
553
- FakeAutomodule.numCallsToRun,
554
- 1,
555
- 'Did not call run on UiAutomodule!'
556
- )
557
- }
558
-
559
27
  @test()
560
28
  protected static async helpOutputsHelpTextToConsole() {
561
29
  const instance = this.CliCommandRunner(['help'])
@@ -591,379 +59,4 @@ export default class CliCommandRunnerTest extends AbstractPackageTest {
591
59
  'Help command should not execute any shell commands!'
592
60
  )
593
61
  }
594
-
595
- @test()
596
- protected static async upgradePackageCreatesInstance() {
597
- const instance = await this.runUpgradePackage()
598
-
599
- assert.isTruthy(
600
- instance,
601
- `Failed to create instance for ${this.upgradePackageCommand}!`
602
- )
603
- }
604
-
605
- @test()
606
- protected static async upgradePackageCreatesNpmAutopackage() {
607
- await this.runUpgradePackage()
608
-
609
- assert.isEqualDeep(
610
- FakeAutopackage.callsToConstructor[0],
611
- {
612
- ...this.infoFromPackageJson,
613
- name: `${this.packageName}`,
614
- gitNamespace: 'neurodevs',
615
- npmNamespace: 'neurodevs',
616
- installDir: this.expandHomeDir('~/dev'),
617
- license: 'MIT',
618
- author: 'Eric Yates <hello@ericthecurious.com>',
619
- },
620
- 'Did not create NpmAutopackage with expected options!'
621
- )
622
- }
623
-
624
- @test()
625
- protected static async upgradePackageRunsNpmAutopackage() {
626
- await this.runUpgradePackage()
627
-
628
- assert.isEqual(
629
- FakeAutopackage.numCallsToRun,
630
- 1,
631
- 'Did not call run on NpmAutopackage!'
632
- )
633
- }
634
-
635
- @test()
636
- protected static async upgradePackageAddsDefaultKeywordsIfMissing() {
637
- await this.runUpgradePackage({
638
- name: this.packageName,
639
- description: this.description,
640
- keywords: [] as string[],
641
- })
642
-
643
- assert.isEqualDeep(
644
- FakeAutopackage.callsToConstructor[0]?.keywords,
645
- this.defaultKeywords,
646
- 'Did not add default keywords!'
647
- )
648
- }
649
-
650
- @test()
651
- protected static async upgradePackageDoesNotOverwriteKeywordsEvenIfDefaultsMissing() {
652
- const keywords = [generateId(), generateId()]
653
-
654
- await this.runUpgradePackage({
655
- name: this.packageName,
656
- description: this.description,
657
- keywords,
658
- })
659
-
660
- assert.isEqualDeep(
661
- FakeAutopackage.callsToConstructor[0]?.keywords,
662
- [...this.defaultKeywords, ...keywords],
663
- 'Should not have overwritten keywords!'
664
- )
665
- }
666
-
667
- @test()
668
- protected static async upgradePackageExtractsPackageNameFromScopedName() {
669
- await this.runUpgradePackage({
670
- name: this.packageName,
671
- description: this.description,
672
- keywords: this.keywordsWithDefaults,
673
- })
674
-
675
- assert.isEqualDeep(
676
- FakeAutopackage.callsToConstructor[0]?.name,
677
- this.packageName,
678
- 'Did not extract package name from scoped name!'
679
- )
680
- }
681
-
682
- private static async runCreateUi(
683
- responses?: Record<string, string | boolean>
684
- ) {
685
- setFakeResponses({
686
- componentName: this.componentName,
687
- ...responses,
688
- })
689
-
690
- const instance = this.CliCommandRunner([this.createUiCommand])
691
- await instance.run()
692
-
693
- return instance
694
- }
695
-
696
- private static setFakeReadFileResultToTsconfig() {
697
- setFakeReadFileResult(this.tsconfigPath, this.originalTsconfigFile)
698
- }
699
-
700
- private static setFakeReadToEmptyPackageJson() {
701
- setFakeReadFileResult('package.json', '{}')
702
- }
703
-
704
- private static setFakeReadToAllInstalledExcept(dep: string) {
705
- setFakeReadFileResult(
706
- 'package.json',
707
- this.allInstalled.replace(dep, '')
708
- )
709
- }
710
-
711
- private static setFakeReadToAllInstalled() {
712
- setFakeReadFileResult('package.json', this.allInstalled)
713
- }
714
-
715
- private static setFakePackageJson(
716
- responses?: Record<string, string | string[]>
717
- ) {
718
- const infoFromPackageJson = {
719
- ...this.infoFromPackageJson,
720
- ...responses,
721
- }
722
-
723
- setFakeReadFileResult(
724
- 'package.json',
725
- JSON.stringify(infoFromPackageJson)
726
- )
727
-
728
- return infoFromPackageJson
729
- }
730
-
731
- private static readonly infoFromPackageJson = {
732
- name: this.packageName,
733
- description: this.description,
734
- keywords: this.keywordsWithDefaults,
735
- }
736
-
737
- private static readonly allInstalled = `
738
- {
739
- "dependencies": {
740
- "react": "^...",
741
- "react-dom": "^..."
742
- },
743
- "devDependencies": {
744
- "@types/react": "^...",
745
- "@types/react-dom": "^...",
746
- "@types/jsdom": "^...",
747
- "@testing-library/react": "^...",
748
- "@testing-library/dom": "^...",
749
- "@testing-library/jest-dom": "^...",
750
- "jsdom": "^..."
751
- }
752
- }
753
- `
754
-
755
- private static readonly allRequiredDependencies = [
756
- 'react',
757
- 'react-dom',
758
- '@types/react',
759
- '@types/react-dom',
760
- '@types/jsdom',
761
- '@testing-library/react',
762
- '@testing-library/dom',
763
- '@testing-library/jest-dom',
764
- 'jsdom',
765
- ]
766
-
767
- private static readonly installDependenciesCommand =
768
- 'yarn add react react-dom'
769
-
770
- private static readonly installDevDependenciesCommand =
771
- 'yarn add -D @types/react @types/react-dom @types/jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom jsdom'
772
-
773
- private static async runCreateImpl(responses?: Record<string, string>) {
774
- setFakeResponses({
775
- interfaceName: this.interfaceName,
776
- implName: this.implName,
777
- ...responses,
778
- })
779
-
780
- const instance = this.CliCommandRunner([this.createImplCommand])
781
- await instance.run()
782
-
783
- return instance
784
- }
785
-
786
- private static async runCreatePackage(responses?: Record<string, string>) {
787
- setFakeResponses({
788
- packageName: this.packageName,
789
- description: this.description,
790
- keywords: this.keywords,
791
- ...responses,
792
- })
793
-
794
- const instance = this.CliCommandRunner([this.createPackageCommand])
795
- await instance.run()
796
-
797
- return instance
798
- }
799
-
800
- private static async runUpgradePackage(
801
- responses?: Record<string, string | string[]>
802
- ) {
803
- this.setFakePackageJson(responses)
804
-
805
- const instance = this.CliCommandRunner([this.upgradePackageCommand])
806
- await instance.run()
807
-
808
- return instance
809
- }
810
-
811
- private static expandHomeDir(inputPath: string): string {
812
- return inputPath.startsWith('~')
813
- ? path.join(os.homedir(), inputPath.slice(1))
814
- : inputPath
815
- }
816
-
817
- private static splitOnCommaOrWhitespace(value: string) {
818
- return value
819
- .split(/[\s,]+/)
820
- .map((v: string) => v.trim())
821
- .filter(Boolean)
822
- }
823
-
824
- private static readonly implTestSaveDir = 'src/__tests__/modules'
825
- private static readonly implModuleSaveDir = 'src/modules'
826
-
827
- private static get implFakeSaveDir() {
828
- return `src/testDoubles/${this.interfaceName}`
829
- }
830
-
831
- private static readonly uiTestSaveDir = 'src/__tests__/ui'
832
- private static readonly uiModuleSaveDir = 'src/ui'
833
-
834
- private static get uiFakeSaveDir() {
835
- return `src/testDoubles/${this.componentName}`
836
- }
837
-
838
- private static readonly tsconfigPath = 'tsconfig.json'
839
- private static readonly randomId = generateId()
840
-
841
- private static readonly originalTsconfigFile = JSON.stringify(
842
- {
843
- [this.randomId]: this.randomId,
844
- compilerOptions: {
845
- [this.randomId]: this.randomId,
846
- },
847
- },
848
- null,
849
- 4
850
- )
851
-
852
- private static readonly updatedTsconfigFile = JSON.stringify(
853
- {
854
- [this.randomId]: this.randomId,
855
- compilerOptions: {
856
- jsx: 'react-jsx',
857
- [this.randomId]: this.randomId,
858
- },
859
- include: ['src'],
860
- },
861
- null,
862
- 4
863
- )
864
-
865
- private static setFakeImplAutomodule() {
866
- ImplAutomodule.Class = FakeAutomodule
867
- FakeAutomodule.resetTestDouble()
868
- }
869
-
870
- private static setFakeUiAutomodule() {
871
- UiAutomodule.Class = FakeAutomodule
872
- FakeAutomodule.resetTestDouble()
873
- }
874
-
875
- private static setFakeAutopackage() {
876
- NpmAutopackage.Class = FakeAutopackage
877
- FakeAutopackage.resetTestDouble()
878
- }
879
-
880
- private static setFakeExec() {
881
- CliCommandRunner.exec = fakeExec as unknown as typeof exec
882
- resetCallsToExec()
883
- }
884
-
885
- private static setFakeLog() {
886
- CliCommandRunner.log = fakeLog as unknown as typeof CliCommandRunner.log
887
- resetCallsToLog()
888
- }
889
-
890
- private static setFakeMkdir() {
891
- CliCommandRunner.mkdir = fakeMkdir as unknown as typeof mkdir
892
- resetCallsToMkdir()
893
- }
894
-
895
- private static setFakePrompts() {
896
- CliCommandRunner.prompts = fakePrompts as unknown as typeof prompts
897
- resetCallsToFakePrompts()
898
- }
899
-
900
- private static setFakeReadFile() {
901
- CliCommandRunner.readFile = fakeReadFile as unknown as typeof readFile
902
- resetCallsToReadFile()
903
-
904
- this.setFakeReadToAllInstalled()
905
- this.setFakeReadFileResultToTsconfig()
906
- }
907
-
908
- private static setFakeWriteFile() {
909
- CliCommandRunner.writeFile =
910
- fakeWriteFile as unknown as typeof writeFile
911
- resetCallsToWriteFile()
912
- }
913
-
914
- private static readonly interfaceNameMessage =
915
- 'What should the interface be called? Example: YourInterface'
916
-
917
- private static readonly implNameMessage =
918
- 'What should the implementation class be called? Example: YourInterfaceImpl'
919
-
920
- private static readonly packageNameMessage =
921
- 'What should the package be called? Example: useful-package'
922
-
923
- private static readonly packageDescriptionMessage =
924
- 'What should the package description be? Example: A useful package.'
925
-
926
- private static readonly componentNameMessage =
927
- 'What should the component be called? Example: YourComponent'
928
-
929
- private static readonly setupTestsFile = `
930
- import { JSDOM } from 'jsdom'
931
-
932
- const jsdom = new JSDOM('<!doctype html><html><body></body></html>', {
933
- url: 'http://localhost',
934
- })
935
-
936
- global.window = jsdom.window as unknown as Window & typeof globalThis
937
- global.document = jsdom.window.document
938
- global.navigator = jsdom.window.navigator
939
- global.HTMLElement = jsdom.window.HTMLElement
940
- global.getComputedStyle = jsdom.window.getComputedStyle
941
-
942
- global.ResizeObserver = class {
943
- public observe() {}
944
- public unobserve() {}
945
- public disconnect() {}
946
- }
947
-
948
- global.SVGElement = jsdom.window.SVGElement
949
- `
950
-
951
- private static readonly helpText = `ndx CLI (Command Line Interface)
952
-
953
- Available commands:
954
-
955
- - create.impl Create implementation for interface with test and fake.
956
- - create.package Create npm package using latest template.
957
- - create.ui Create React component with test and fake.
958
- - upgrade.package Upgrade existing npm package to latest template.
959
- - help, --help, -h Show this help text.
960
-
961
- Usage:
962
-
963
- - ndx <command> [options]
964
- `
965
-
966
- private static CliCommandRunner(args: string[]) {
967
- return CliCommandRunner.Create(args)
968
- }
969
62
  }