@neurodevs/meta-node 0.19.11 → 0.19.13

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.
@@ -1,22 +1,20 @@
1
1
  import { ChildProcess, exec as execSync } from 'child_process'
2
2
  import { readFile, writeFile } from 'fs/promises'
3
3
  import { mkdir } from 'fs/promises'
4
+ import path from 'path'
4
5
  import { promisify } from 'util'
5
6
  import {
6
- callsToChdir,
7
7
  callsToExec,
8
8
  callsToFetch,
9
9
  callsToMkdir,
10
10
  callsToReadFile,
11
11
  callsToWriteFile,
12
- fakeChdir,
13
12
  fakeExec,
14
13
  fakeFetch,
15
14
  fakeMkdir,
16
15
  fakePathExists,
17
16
  fakeReadFile,
18
17
  fakeWriteFile,
19
- resetCallsToChdir,
20
18
  resetCallsToExec,
21
19
  resetCallsToFetch,
22
20
  resetCallsToMkdir,
@@ -34,6 +32,7 @@ import GitAutocommit from '../../impl/GitAutocommit.js'
34
32
  import NpmAutopackage, {
35
33
  Autopackage,
36
34
  AutopackageOptions,
35
+ TsConfig,
37
36
  } from '../../impl/NpmAutopackage.js'
38
37
  import FakeAutocommit from '../../testDoubles/Autocommit/FakeAutocommit.js'
39
38
  import AbstractPackageTest from '../AbstractPackageTest.js'
@@ -43,10 +42,120 @@ const exec = promisify(execSync)
43
42
  export default class NpmAutopackageTest extends AbstractPackageTest {
44
43
  private static instance: Autopackage
45
44
 
45
+ private static readonly installDir = this.generateId()
46
+ private static readonly description = this.generateId()
47
+ private static readonly gitNamespace = this.generateId()
48
+ private static readonly npmNamespace = this.generateId()
49
+ private static readonly keywords = [this.generateId(), this.generateId()]
50
+ private static readonly license = this.generateId()
51
+ private static readonly author = this.generateId()
52
+ private static readonly githubToken = this.generateId()
53
+ private static readonly randomId = this.generateId()
54
+
55
+ private static readonly packageDir = path.join(
56
+ this.installDir,
57
+ this.packageName
58
+ )
59
+
60
+ private static readonly packageJsonPath = path.join(
61
+ this.packageDir,
62
+ 'package.json'
63
+ )
64
+
65
+ private static readonly gitignorePath = path.join(
66
+ this.packageDir,
67
+ '.gitignore'
68
+ )
69
+
70
+ private static readonly originalGitignore = this.generateId()
71
+
72
+ private static readonly updatedGitignore = `${this.originalGitignore}\nbuild/`
73
+
74
+ private static readonly tsconfigPath = path.join(
75
+ this.packageDir,
76
+ 'tsconfig.json'
77
+ )
78
+
79
+ private static readonly tasksJsonPath = path.join(
80
+ this.packageDir,
81
+ '.vscode',
82
+ 'tasks.json'
83
+ )
84
+
85
+ private static readonly testDirPath = path.join(
86
+ this.packageDir,
87
+ 'src',
88
+ '__tests__'
89
+ )
90
+
91
+ private static readonly abstractTestPath = path.join(
92
+ this.testDirPath,
93
+ 'AbstractPackageTest.ts'
94
+ )
95
+
96
+ private static readonly eslintConfigPath = path.join(
97
+ this.packageDir,
98
+ 'eslint.config.js'
99
+ )
100
+
101
+ private static readonly prettierConfigPath = path.join(
102
+ this.packageDir,
103
+ 'prettier.config.js'
104
+ )
105
+
106
+ private static readonly customLib = this.generateId()
107
+ private static readonly customType = this.generateId()
108
+ private static readonly customInclude = this.generateId()
109
+ private static readonly customOption = this.generateId()
110
+
111
+ private static readonly setupVscodeCmd = 'spruce setup.vscode --all true'
112
+
113
+ private static readonly checkGenerateIdVersionCmd = `yarn info @neurodevs/generate-id version --silent`
114
+ private static readonly checkNodeTddVersionCmd = `yarn info @neurodevs/node-tdd version --silent`
115
+ private static readonly checkEslintConfigNdxVersionCmd = `yarn info @neurodevs/eslint-config-ndx version --silent`
116
+ private static readonly checkPrettierConfigNdxVersionCmd = `yarn info @neurodevs/prettier-config-ndx version --silent`
117
+
118
+ private static readonly dependencies = {
119
+ [this.generateId()]: this.generateId(),
120
+ [this.generateId()]: this.generateId(),
121
+ }
122
+
123
+ private static readonly yarnInstallDevDepsCommand =
124
+ 'yarn add -D @neurodevs/generate-id @neurodevs/node-tdd @neurodevs/eslint-config-ndx @neurodevs/prettier-config-ndx'
125
+
126
+ private static readonly abstractTestFile = `import AbstractModuleTest from '@neurodevs/node-tdd'
127
+
128
+ export default abstract class AbstractPackageTest extends AbstractModuleTest {
129
+ protected static async beforeEach() {
130
+ await super.beforeEach()
131
+ }
132
+ }
133
+ `
134
+
135
+ private static readonly eslintConfigFile = `import esConfigNdx from './src/eslint.config.js'
136
+
137
+ export default esConfigNdx
138
+ `
139
+
140
+ private static readonly prettierConfigFile = `import prettierConfigNdx from '@neurodevs/prettier-config-ndx'
141
+
142
+ export default prettierConfigNdx
143
+ `
144
+
145
+ private static readonly defaultOptions = {
146
+ installDir: this.installDir,
147
+ name: this.packageName,
148
+ description: this.description,
149
+ gitNamespace: this.gitNamespace,
150
+ npmNamespace: this.npmNamespace,
151
+ keywords: this.keywords,
152
+ license: this.license,
153
+ author: this.author,
154
+ }
155
+
46
156
  protected static async beforeEach() {
47
157
  await super.beforeEach()
48
158
 
49
- this.fakeChdir()
50
159
  this.fakeExec()
51
160
  this.fakeFetch()
52
161
  this.fakeMkdir()
@@ -101,7 +210,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
101
210
  'Content-Type': 'application/json',
102
211
  },
103
212
  body: JSON.stringify({
104
- name: this.name,
213
+ name: this.packageName,
105
214
  private: false,
106
215
  description: this.description,
107
216
  auto_init: true,
@@ -114,46 +223,27 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
114
223
  )
115
224
  }
116
225
 
117
- @test()
118
- protected static async thenChdirToInstallDir() {
119
- await this.run()
120
-
121
- assert.isEqual(
122
- callsToChdir[0],
123
- this.installDir,
124
- 'Did not change to installDir!'
125
- )
126
- }
127
-
128
226
  @test()
129
227
  protected static async thenGitClone() {
130
228
  await this.run()
131
229
 
132
- assert.isEqual(
133
- callsToExec[0]?.command,
134
- `git clone https://github.com/${this.gitNamespace}/${this.name}.git`,
230
+ assert.isEqualDeep(
231
+ callsToExec[0],
232
+ {
233
+ command: `git clone https://github.com/${this.gitNamespace}/${this.packageName}.git`,
234
+ options: { cwd: this.installDir },
235
+ },
135
236
  'Did not call git clone!'
136
237
  )
137
238
  }
138
239
 
139
- @test()
140
- protected static async thenChdirToPackageDir() {
141
- await this.run()
142
-
143
- assert.isEqual(
144
- callsToChdir[1],
145
- this.packageDir,
146
- 'Did not change to packageDir!'
147
- )
148
- }
149
-
150
240
  @test()
151
241
  protected static async thenGitFetchOrigin() {
152
242
  await this.run()
153
243
 
154
- assert.isEqual(
155
- callsToExec[1]?.command,
156
- `git fetch origin`,
244
+ assert.isEqualDeep(
245
+ callsToExec[1],
246
+ { command: `git fetch origin`, options: { cwd: this.packageDir } },
157
247
  'Did not call git fetch origin!'
158
248
  )
159
249
  }
@@ -162,9 +252,12 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
162
252
  protected static async thenGitFetchResetHard() {
163
253
  await this.run()
164
254
 
165
- assert.isEqual(
166
- callsToExec[2]?.command,
167
- `git reset --hard origin/main`,
255
+ assert.isEqualDeep(
256
+ callsToExec[2],
257
+ {
258
+ command: `git reset --hard origin/main`,
259
+ options: { cwd: this.packageDir },
260
+ },
168
261
  'Did not call git reset hard!'
169
262
  )
170
263
  }
@@ -173,9 +266,12 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
173
266
  protected static async thenSpruceCreateModule() {
174
267
  await this.run()
175
268
 
176
- assert.isEqual(
177
- callsToExec[4]?.command,
178
- this.createModuleCmd,
269
+ assert.isEqualDeep(
270
+ callsToExec[4],
271
+ {
272
+ command: this.createModuleCmd,
273
+ options: { cwd: this.packageDir },
274
+ },
179
275
  'Did not call "spruce create.module"!'
180
276
  )
181
277
  }
@@ -185,8 +281,11 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
185
281
  await this.run()
186
282
 
187
283
  assert.isEqualDeep(
188
- FakeAutocommit.callsToConstructor[0]?.commitMessage,
189
- `patch: create package (@neurodevs/meta-node: ${this.metaNodeVersion})`,
284
+ FakeAutocommit.callsToConstructor[0],
285
+ {
286
+ commitMessage: `patch: create package (@neurodevs/meta-node: ${this.metaNodeVersion})`,
287
+ cwd: this.packageDir,
288
+ },
190
289
  'Did not commit create package changes!'
191
290
  )
192
291
  }
@@ -254,8 +353,11 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
254
353
  await this.run()
255
354
 
256
355
  assert.isEqualDeep(
257
- FakeAutocommit.callsToConstructor[1]?.commitMessage,
258
- `patch: update package.json (@neurodevs/meta-node: ${this.metaNodeVersion})`,
356
+ FakeAutocommit.callsToConstructor[1],
357
+ {
358
+ commitMessage: `patch: update package.json (@neurodevs/meta-node: ${this.metaNodeVersion})`,
359
+ cwd: this.packageDir,
360
+ },
259
361
  'Did not commit update package changes!'
260
362
  )
261
363
  }
@@ -268,7 +370,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
268
370
  callsToWriteFile[1],
269
371
  {
270
372
  file: this.gitignorePath,
271
- data: this.buildDirGitignorePattern,
373
+ data: '\nbuild/\n',
272
374
  options: { encoding: 'utf-8', flag: 'a' },
273
375
  },
274
376
  'Did not update .gitignore as expected!'
@@ -280,19 +382,54 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
280
382
  await this.run()
281
383
 
282
384
  assert.isEqualDeep(
283
- FakeAutocommit.callsToConstructor[2]?.commitMessage,
284
- `patch: add build dir to gitignore (@neurodevs/meta-node: ${this.metaNodeVersion})`,
385
+ FakeAutocommit.callsToConstructor[2],
386
+ {
387
+ commitMessage: `patch: add build dir to gitignore (@neurodevs/meta-node: ${this.metaNodeVersion})`,
388
+ cwd: this.packageDir,
389
+ },
285
390
  'Did not commit .gitignore changes!'
286
391
  )
287
392
  }
288
393
 
394
+ @test()
395
+ protected static async thenUpdatesTsconfig() {
396
+ await this.run()
397
+
398
+ assert.isEqualDeep(
399
+ callsToWriteFile[2],
400
+ {
401
+ file: this.tsconfigPath,
402
+ data: JSON.stringify(this.updatedTsconfig, null, 4) + '\n',
403
+ options: { encoding: 'utf-8', flag: 'a' },
404
+ },
405
+ 'Did not update tsconfig as expected!'
406
+ )
407
+ }
408
+
409
+ @test()
410
+ protected static async thenCommitsUpdateTsconfig() {
411
+ await this.run()
412
+
413
+ assert.isEqualDeep(
414
+ FakeAutocommit.callsToConstructor[3],
415
+ {
416
+ commitMessage: `patch: update tsconfig (@neurodevs/meta-node: ${this.metaNodeVersion})`,
417
+ cwd: this.packageDir,
418
+ },
419
+ 'Did not commit tsconfig changes!'
420
+ )
421
+ }
422
+
289
423
  @test()
290
424
  protected static async thenSpruceSetupVscode() {
291
425
  await this.run()
292
426
 
293
- assert.isEqual(
294
- callsToExec[5]?.command,
295
- this.setupVscodeCmd,
427
+ assert.isEqualDeep(
428
+ callsToExec[5],
429
+ {
430
+ command: this.setupVscodeCmd,
431
+ options: { cwd: this.packageDir },
432
+ },
296
433
  'Did not call "spruce setup.vscode"!'
297
434
  )
298
435
  }
@@ -302,8 +439,11 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
302
439
  await this.run()
303
440
 
304
441
  assert.isEqualDeep(
305
- FakeAutocommit.callsToConstructor[3]?.commitMessage,
306
- `patch: setup vscode (@neurodevs/meta-node: ${this.metaNodeVersion})`,
442
+ FakeAutocommit.callsToConstructor[4],
443
+ {
444
+ commitMessage: `patch: setup vscode (@neurodevs/meta-node: ${this.metaNodeVersion})`,
445
+ cwd: this.packageDir,
446
+ },
307
447
  'Did not commit vscode changes!'
308
448
  )
309
449
  }
@@ -312,7 +452,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
312
452
  protected static async thenUpdatesVscodeTasksJson() {
313
453
  await this.run()
314
454
 
315
- assert.isEqualDeep(callsToWriteFile[2], {
455
+ assert.isEqualDeep(callsToWriteFile[3], {
316
456
  file: this.tasksJsonPath,
317
457
  data: this.updatedTasksJson,
318
458
  options: { encoding: 'utf-8' },
@@ -324,30 +464,41 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
324
464
  await this.run()
325
465
 
326
466
  assert.isEqualDeep(
327
- FakeAutocommit.callsToConstructor[4]?.commitMessage,
328
- `patch: update vscode tasks.json (@neurodevs/meta-node: ${this.metaNodeVersion})`,
467
+ FakeAutocommit.callsToConstructor[5],
468
+ {
469
+ commitMessage: `patch: update vscode tasks.json (@neurodevs/meta-node: ${this.metaNodeVersion})`,
470
+ cwd: this.packageDir,
471
+ },
329
472
  'Did not commit updated vscode tasks.json changes!'
330
473
  )
331
474
  }
332
475
 
333
476
  @test()
334
477
  protected static async thenInstallsDefaultDevDependencies() {
478
+ this.setShouldInstallDevDeps()
335
479
  await this.run()
336
480
 
337
- assert.isEqual(
338
- callsToExec[8]?.command,
339
- this.yarnInstallDevDepsCommand,
481
+ assert.isEqualDeep(
482
+ callsToExec[10],
483
+ {
484
+ command: this.yarnInstallDevDepsCommand,
485
+ options: { cwd: this.packageDir },
486
+ },
340
487
  'Did not install default devDependencies!'
341
488
  )
342
489
  }
343
490
 
344
491
  @test()
345
492
  protected static async thenCommitsInstallDefaultDevDependencies() {
493
+ this.setShouldInstallDevDeps()
346
494
  await this.run()
347
495
 
348
496
  assert.isEqualDeep(
349
- FakeAutocommit.callsToConstructor[5]?.commitMessage,
350
- `patch: install default devDependencies (@neurodevs/meta-node: ${this.metaNodeVersion})`,
497
+ FakeAutocommit.callsToConstructor[6],
498
+ {
499
+ commitMessage: `patch: install default devDependencies (@neurodevs/meta-node: ${this.metaNodeVersion})`,
500
+ cwd: this.packageDir,
501
+ },
351
502
  'Did not commit install devDependencies changes!'
352
503
  )
353
504
  }
@@ -359,7 +510,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
359
510
  assert.isEqualDeep(
360
511
  callsToMkdir[0],
361
512
  {
362
- path: 'src/__tests__',
513
+ path: this.testDirPath,
363
514
  options: { recursive: true },
364
515
  },
365
516
  'Did not install tests directory!'
@@ -368,13 +519,14 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
368
519
 
369
520
  @test()
370
521
  protected static async thenInstallsAbstractPackageTest() {
522
+ this.setShouldInstallDevDeps()
371
523
  await this.run()
372
524
 
373
525
  assert.isEqualDeep(
374
- callsToWriteFile[3],
526
+ callsToWriteFile[4],
375
527
  {
376
- file: this.abstractPackageTestPath,
377
- data: this.abstractPackageTestFile,
528
+ file: this.abstractTestPath,
529
+ data: this.abstractTestFile,
378
530
  options: { encoding: 'utf-8' },
379
531
  },
380
532
  'Did not install AbstractPackageTest!'
@@ -383,53 +535,208 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
383
535
 
384
536
  @test()
385
537
  protected static async thenCommitsInstallAbstractPackageTest() {
538
+ this.setShouldInstallDevDeps()
386
539
  await this.run()
387
540
 
388
541
  assert.isEqualDeep(
389
- FakeAutocommit.callsToConstructor[6]?.commitMessage,
390
- `patch: install AbstractPackageTest (@neurodevs/meta-node: ${this.metaNodeVersion})`,
542
+ FakeAutocommit.callsToConstructor[7],
543
+ {
544
+ commitMessage: `patch: install AbstractPackageTest (@neurodevs/meta-node: ${this.metaNodeVersion})`,
545
+ cwd: this.packageDir,
546
+ },
391
547
  'Did not commit install AbstractPackageTest changes!'
392
548
  )
393
549
  }
394
550
 
551
+ @test()
552
+ protected static async thenInstallsEslintConfigFile() {
553
+ this.setShouldInstallDevDeps()
554
+ await this.run()
555
+
556
+ assert.isEqualDeep(
557
+ callsToWriteFile[5],
558
+ {
559
+ file: this.eslintConfigPath,
560
+ data: this.eslintConfigFile,
561
+ options: { encoding: 'utf-8' },
562
+ },
563
+ 'Did not install eslint.config.js!'
564
+ )
565
+ }
566
+
567
+ @test()
568
+ protected static async thenCommitsInstallEslintConfigFile() {
569
+ this.setShouldInstallDevDeps()
570
+ await this.run()
571
+
572
+ assert.isEqualDeep(
573
+ FakeAutocommit.callsToConstructor[8],
574
+ {
575
+ commitMessage: `patch: install eslint.config.js (@neurodevs/meta-node: ${this.metaNodeVersion})`,
576
+ cwd: this.packageDir,
577
+ },
578
+ 'Did not commit install eslint.config.js changes!'
579
+ )
580
+ }
581
+
582
+ @test()
583
+ protected static async thenInstallsPrettierConfigFile() {
584
+ this.setShouldInstallDevDeps()
585
+ await this.run()
586
+
587
+ assert.isEqualDeep(
588
+ callsToWriteFile[6],
589
+ {
590
+ file: this.prettierConfigPath,
591
+ data: this.prettierConfigFile,
592
+ options: { encoding: 'utf-8' },
593
+ },
594
+ 'Did not install prettier.config.js!'
595
+ )
596
+ }
597
+
598
+ @test()
599
+ protected static async thenCommitsInstallPrettierConfigFile() {
600
+ this.setShouldInstallDevDeps()
601
+ await this.run()
602
+
603
+ assert.isEqualDeep(
604
+ FakeAutocommit.callsToConstructor[9],
605
+ {
606
+ commitMessage: `patch: install prettier.config.js (@neurodevs/meta-node: ${this.metaNodeVersion})`,
607
+ cwd: this.packageDir,
608
+ },
609
+ 'Did not commit install prettier.config.js changes!'
610
+ )
611
+ }
612
+
395
613
  @test()
396
614
  protected static async lastlyOpensVscodeAtEnd() {
397
615
  await this.run()
398
616
 
399
- assert.isEqual(
400
- callsToExec[9]?.command,
401
- 'code .',
617
+ assert.isEqualDeep(
618
+ callsToExec[10],
619
+ { command: 'code .', options: { cwd: this.packageDir } },
402
620
  'Did not open vscode at end!'
403
621
  )
404
622
  }
405
623
 
406
624
  @test()
407
- protected static async doesNotCreateRepoInGithubOrgIfDone() {
408
- const fakeResponse = new Response(null, {
409
- status: 200,
410
- statusText: 'OK',
625
+ protected static async installsDevDependenciesIfGenerateIdNotLatest() {
626
+ setFakeExecResult(this.checkGenerateIdVersionCmd, {
627
+ stdout: '0.0.1',
628
+ } as unknown as ChildProcess)
629
+
630
+ await this.runTwice()
631
+
632
+ const calls = callsToExec.filter(
633
+ (call) => call?.command === this.yarnInstallDevDepsCommand
634
+ )
635
+
636
+ assert.isEqualDeep(
637
+ calls[0],
638
+ {
639
+ command: this.yarnInstallDevDepsCommand,
640
+ options: { cwd: this.packageDir },
641
+ },
642
+ 'Should install default devDependencies if not already installed!'
643
+ )
644
+ }
645
+
646
+ @test()
647
+ protected static async installsDevDependenciesIfNodeTddNotLatest() {
648
+ this.setShouldInstallDevDeps()
649
+ await this.runTwice()
650
+
651
+ const calls = callsToExec.filter(
652
+ (call) => call?.command === this.yarnInstallDevDepsCommand
653
+ )
654
+
655
+ assert.isEqualDeep(
656
+ calls[0],
657
+ {
658
+ command: this.yarnInstallDevDepsCommand,
659
+ options: { cwd: this.packageDir },
660
+ },
661
+ 'Should install default devDependencies if not already installed!'
662
+ )
663
+ }
664
+
665
+ @test()
666
+ protected static async installsDevDependenciesIfEslintConfigNdxNotLatest() {
667
+ this.setShouldInstallDevDeps()
668
+ await this.runTwice()
669
+
670
+ const calls = callsToExec.filter(
671
+ (call) => call?.command === this.yarnInstallDevDepsCommand
672
+ )
673
+
674
+ assert.isEqualDeep(
675
+ calls[0],
676
+ {
677
+ command: this.yarnInstallDevDepsCommand,
678
+ options: { cwd: this.packageDir },
679
+ },
680
+ 'Should install default devDependencies if not already installed!'
681
+ )
682
+ }
683
+
684
+ @test()
685
+ protected static async installsDevDependenciesIfPrettierConfigNdxNotLatest() {
686
+ this.setShouldInstallDevDeps()
687
+ await this.runTwice()
688
+
689
+ const calls = callsToExec.filter(
690
+ (call) => call?.command === this.yarnInstallDevDepsCommand
691
+ )
692
+
693
+ assert.isEqualDeep(
694
+ calls[0],
695
+ {
696
+ command: this.yarnInstallDevDepsCommand,
697
+ options: { cwd: this.packageDir },
698
+ },
699
+ 'Should install default devDependencies if not already installed!'
700
+ )
701
+ }
702
+
703
+ @test()
704
+ protected static async makeNpmNamespaceOptional() {
705
+ resetCallsToWriteFile()
706
+
707
+ const instance = this.NpmAutopackage({
708
+ npmNamespace: undefined,
411
709
  })
412
710
 
413
- setFakeFetchResponse(this.reposUrl, fakeResponse)
711
+ await instance.run()
712
+
713
+ assert.doesInclude(
714
+ callsToWriteFile[0]?.data,
715
+ `"name": "${this.packageName}"`,
716
+ 'Did not handle missing npmNamespace!'
717
+ )
718
+ }
414
719
 
415
- await this.createAndRunAutopackage()
720
+ @test()
721
+ protected static async doesNotCreateRepoInGithubOrgIfDone() {
722
+ await this.runTwice()
416
723
 
417
724
  const numCalls = callsToFetch.filter(
418
725
  (call) => call.input === this.orgsUrl
419
726
  ).length
420
727
 
421
- assert.isEqual(numCalls, 0, 'Should not have created repo!')
728
+ assert.isEqual(numCalls, 1, 'Should have created repo once!')
422
729
  }
423
730
 
424
731
  @test()
425
732
  protected static async doesNotCloneRepoIfDone() {
426
- await this.createAndRunAutopackage()
733
+ await this.runTwice()
427
734
 
428
735
  assert.isEqual(
429
736
  callsToExec.filter(
430
737
  (call) =>
431
738
  call?.command ===
432
- `git clone https://github.com/${this.gitNamespace}/${this.name}.git`
739
+ `git clone https://github.com/${this.gitNamespace}/${this.packageName}.git`
433
740
  ).length,
434
741
  1,
435
742
  'Did not clone repo once!'
@@ -438,7 +745,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
438
745
 
439
746
  @test()
440
747
  protected static async doesNotSpruceCreateModuleIfDone() {
441
- await this.createAndRunAutopackage()
748
+ await this.runTwice()
442
749
 
443
750
  assert.isEqual(
444
751
  callsToExec.filter((call) => call?.command === this.createModuleCmd)
@@ -450,7 +757,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
450
757
 
451
758
  @test()
452
759
  protected static async doesNotRunSetupVscodeIfDone() {
453
- await this.createAndRunAutopackage()
760
+ await this.runTwice()
454
761
 
455
762
  assert.isEqual(
456
763
  callsToExec.filter((call) => call?.command === this.setupVscodeCmd)
@@ -462,7 +769,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
462
769
 
463
770
  @test()
464
771
  protected static async doesNotCommitCreatePackageIfDone() {
465
- await this.createAndRunAutopackage()
772
+ await this.runTwice()
466
773
 
467
774
  assert.isEqual(
468
775
  FakeAutocommit.callsToConstructor.filter(
@@ -477,7 +784,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
477
784
 
478
785
  @test()
479
786
  protected static async doesNotCommitUpdatePackageIfDone() {
480
- await this.createAndRunAutopackage()
787
+ await this.runTwice()
481
788
 
482
789
  assert.isEqual(
483
790
  FakeAutocommit.callsToConstructor.filter(
@@ -492,7 +799,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
492
799
 
493
800
  @test()
494
801
  protected static async doesNotCommitUpdateGitignoreIfDone() {
495
- await this.createAndRunAutopackage()
802
+ await this.runTwice()
496
803
 
497
804
  assert.isEqual(
498
805
  FakeAutocommit.callsToConstructor.filter(
@@ -505,9 +812,24 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
505
812
  )
506
813
  }
507
814
 
815
+ @test()
816
+ protected static async doesNotCommitUpdateTsconfigIfDone() {
817
+ await this.runTwice()
818
+
819
+ assert.isEqual(
820
+ FakeAutocommit.callsToConstructor.filter(
821
+ (call) =>
822
+ call?.commitMessage ===
823
+ `patch: update tsconfig (@neurodevs/meta-node: ${this.metaNodeVersion})`
824
+ ).length,
825
+ 1,
826
+ 'Did not commit tsconfig changes once!'
827
+ )
828
+ }
829
+
508
830
  @test()
509
831
  protected static async doesNotCommitSetupVscodeIfDone() {
510
- await this.createAndRunAutopackage()
832
+ await this.runTwice()
511
833
 
512
834
  assert.isEqual(
513
835
  FakeAutocommit.callsToConstructor.filter(
@@ -522,7 +844,7 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
522
844
 
523
845
  @test()
524
846
  protected static async doesNotOverrideOriginalDependencies() {
525
- await this.createAndRunAutopackage()
847
+ await this.runTwice()
526
848
 
527
849
  assert.isEqualDeep(
528
850
  JSON.parse(callsToWriteFile[0]?.data).dependencies,
@@ -533,23 +855,21 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
533
855
 
534
856
  @test()
535
857
  protected static async doesNotUpdateTasksJsonIfAlreadyDone() {
536
- setFakeReadFileResult(this.tasksJsonPath, this.updatedTasksJson)
537
-
538
- await this.createAndRunAutopackage()
858
+ await this.runTwice()
539
859
 
540
860
  assert.isEqualDeep(
541
861
  callsToWriteFile.filter((call) => call.file === this.tasksJsonPath)
542
862
  .length,
543
- 0,
863
+ 1,
544
864
  'Did not update tasks.json once!'
545
865
  )
546
866
  }
547
867
 
548
868
  @test()
549
869
  protected static async doesNotOpenVscodeIfNotCloned() {
550
- setPathShouldExist(this.name, true)
870
+ setPathShouldExist(this.packageDir, true)
551
871
 
552
- await this.createAndRunAutopackage()
872
+ await this.run()
553
873
 
554
874
  assert.isFalse(
555
875
  callsToExec.some((call) => call?.command === 'code .'),
@@ -558,105 +878,80 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
558
878
  }
559
879
 
560
880
  @test()
561
- protected static async installsDevDependenciesIfGenerateIdNotLatest() {
562
- setFakeExecResult(this.checkGenerateIdVersionCmd, {
563
- stdout: '0.0.1',
564
- } as unknown as ChildProcess)
565
-
566
- await this.createAndRunAutopackage()
567
-
568
- const calls = callsToExec.filter(
569
- (call) => call?.command === this.yarnInstallDevDepsCommand
881
+ protected static async doesNotThrowIfGenerateIdNotInPackageJson() {
882
+ setFakeReadFileResult(
883
+ this.packageJsonPath,
884
+ this.originalPackageJson.replace('@neurodevs/generate-id', '')
570
885
  )
571
886
 
572
- assert.isEqual(
573
- calls.length,
574
- 1,
575
- 'Should not install default devDependencies if already installed!'
576
- )
887
+ await this.runTwice()
577
888
  }
578
889
 
579
890
  @test()
580
- protected static async installsDevDependenciesIfNodeTddNotLatest() {
581
- setFakeExecResult(this.checkGenerateIdVersionCmd, {
582
- stdout: '1.0.0',
583
- } as unknown as ChildProcess)
584
-
585
- setFakeExecResult(this.checkNodeTddVersionCmd, {
586
- stdout: '0.0.1',
587
- } as unknown as ChildProcess)
891
+ protected static async doesNotInstallAbstractPackageTestIfTsExists() {
892
+ setPathShouldExist(this.abstractTestPath, true)
588
893
 
589
- await this.createAndRunAutopackage()
894
+ await this.run()
590
895
 
591
- const calls = callsToExec.filter(
592
- (call) => call?.command === this.yarnInstallDevDepsCommand
896
+ const calls = callsToWriteFile.filter(
897
+ (call) => call.file === this.abstractTestPath
593
898
  )
594
899
 
595
900
  assert.isEqual(
596
901
  calls.length,
597
- 1,
598
- 'Should not install default devDependencies if already installed!'
599
- )
600
- }
601
-
602
- @test()
603
- protected static async doesNotThrowIfGenerateIdNotInPackageJson() {
604
- setFakeReadFileResult(
605
- this.packageJsonPath,
606
- this.originalPackageJson.replace('@neurodevs/generate-id', '')
902
+ 0,
903
+ 'Should not install AbstractPackageTest.ts if already exists!'
607
904
  )
608
-
609
- await this.createAndRunAutopackage()
610
905
  }
611
906
 
612
907
  @test()
613
- protected static async doesNotInstallAbstractPackageTestIfTsExists() {
614
- setPathShouldExist(this.abstractPackageTestPath, true)
908
+ protected static async doesNotInstallAbstractPackageTestIfTsxExists() {
909
+ setPathShouldExist(`${this.abstractTestPath}x`, true)
615
910
 
616
- await this.createAndRunAutopackage()
911
+ await this.run()
617
912
 
618
913
  const calls = callsToWriteFile.filter(
619
- (call) => call.file === this.abstractPackageTestPath
914
+ (call) => call.file === this.abstractTestPath
620
915
  )
621
916
 
622
917
  assert.isEqual(
623
918
  calls.length,
624
919
  0,
625
- 'Should not install AbstractPackageTest.ts if already exists!'
920
+ 'Should not install AbstractPackageTest.tsx if already exists!'
626
921
  )
627
922
  }
628
923
 
629
924
  @test()
630
- protected static async doesNotInstallAbstractPackageTestIfTsxExists() {
631
- setPathShouldExist(`${this.abstractPackageTestPath}x`, true)
925
+ protected static async doesNotInstallEslintConfigFileIfExists() {
926
+ setPathShouldExist(this.eslintConfigPath, true)
632
927
 
633
- await this.createAndRunAutopackage()
928
+ await this.run()
634
929
 
635
930
  const calls = callsToWriteFile.filter(
636
- (call) => call.file === this.abstractPackageTestPath
931
+ (call) => call.file === this.eslintConfigPath
637
932
  )
638
933
 
639
934
  assert.isEqual(
640
935
  calls.length,
641
936
  0,
642
- 'Should not install AbstractPackageTest.tsx if already exists!'
937
+ 'Should not install eslint.config.js if already exists!'
643
938
  )
644
939
  }
645
940
 
646
941
  @test()
647
- protected static async makeNpmNamespaceOptional() {
648
- resetCallsToWriteFile()
942
+ protected static async doesNotInstallPrettierConfigFileIfExists() {
943
+ setPathShouldExist(this.prettierConfigPath, true)
649
944
 
650
- const instance = this.NpmAutopackage({
651
- npmNamespace: undefined,
652
- })
945
+ await this.run()
653
946
 
654
- await instance.run()
947
+ const calls = callsToWriteFile.filter(
948
+ (call) => call.file === this.prettierConfigPath
949
+ )
655
950
 
656
- assert.doesInclude(
657
- callsToWriteFile[0]?.data,
658
- `"name": "${this.name}"`,
659
- 'Did not handle missing npmNamespace!'
951
+ assert.isEqual(
952
+ calls.length,
953
+ 0,
954
+ 'Should not install prettier.config.js if already exists!'
660
955
  )
661
956
  }
662
957
 
@@ -664,32 +959,47 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
664
959
  await this.instance.run()
665
960
  }
666
961
 
667
- private static async createAndRunAutopackage() {
668
- const instance = this.NpmAutopackage()
669
- await instance.run()
670
- }
962
+ private static async runTwice() {
963
+ await this.run()
671
964
 
672
- private static get scopedPackageName() {
673
- return `@${this.npmNamespace}/${this.name}`
965
+ setPathShouldExist(this.packageDir, true)
966
+ setPathShouldExist(this.packageJsonPath, true)
967
+ setPathShouldExist(this.abstractTestPath, true)
968
+ setPathShouldExist(this.tasksJsonPath, true)
969
+
970
+ setFakeReadFileResult(this.packageJsonPath, this.updatedPackageJson)
971
+ setFakeReadFileResult(this.gitignorePath, this.updatedGitignore)
972
+ setFakeReadFileResult(this.tasksJsonPath, this.updatedTasksJson)
973
+
974
+ setFakeReadFileResult(
975
+ this.tsconfigPath,
976
+ JSON.stringify(this.updatedTsconfig)
977
+ )
978
+
979
+ const fakeResponse = new Response(null, {
980
+ status: 200,
981
+ statusText: 'OK',
982
+ })
983
+
984
+ setFakeFetchResponse(this.reposUrl, fakeResponse)
985
+
986
+ await this.run()
674
987
  }
675
988
 
676
- private static get packageDir() {
677
- return this.name
989
+ private static setShouldInstallDevDeps() {
990
+ setFakeExecResult(this.checkGenerateIdVersionCmd, {
991
+ stdout: '0.0.1',
992
+ } as unknown as ChildProcess)
678
993
  }
679
994
 
680
- private static readonly packageJsonPath = 'package.json'
681
- private static readonly gitignorePath = '.gitignore'
682
- private static readonly buildDirGitignorePattern = '\nbuild/\n'
995
+ private static get scopedPackageName() {
996
+ return `@${this.npmNamespace}/${this.packageName}`
997
+ }
683
998
 
684
999
  private static get createModuleCmd() {
685
- return `spruce create.module --name "${this.name}" --destination "." --description "${this.description}"`
1000
+ return `spruce create.module --name "${this.packageName}" --destination "." --description "${this.description}"`
686
1001
  }
687
1002
 
688
- private static readonly setupVscodeCmd = 'spruce setup.vscode --all true'
689
-
690
- private static readonly checkGenerateIdVersionCmd = `yarn info @neurodevs/generate-id version --silent`
691
- private static readonly checkNodeTddVersionCmd = `yarn info @neurodevs/node-tdd version --silent`
692
-
693
1003
  private static orderJsonKeys(
694
1004
  json: Record<string, unknown>,
695
1005
  keyOrder: string[]
@@ -713,16 +1023,27 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
713
1023
  return ordered
714
1024
  }
715
1025
 
716
- private static fakeChdir() {
717
- NpmAutopackage.chdir = fakeChdir
718
- resetCallsToChdir()
719
- }
720
-
721
1026
  private static fakeExec() {
722
1027
  NpmAutopackage.exec = fakeExec as unknown as typeof exec
723
1028
  resetCallsToExec()
724
1029
 
725
1030
  this.setFakeMetaNodeVersion()
1031
+
1032
+ setFakeExecResult(this.checkGenerateIdVersionCmd, {
1033
+ stdout: '1.0.0',
1034
+ } as unknown as ChildProcess)
1035
+
1036
+ setFakeExecResult(this.checkNodeTddVersionCmd, {
1037
+ stdout: '1.0.0',
1038
+ } as unknown as ChildProcess)
1039
+
1040
+ setFakeExecResult(this.checkEslintConfigNdxVersionCmd, {
1041
+ stdout: '1.0.0',
1042
+ } as unknown as ChildProcess)
1043
+
1044
+ setFakeExecResult(this.checkPrettierConfigNdxVersionCmd, {
1045
+ stdout: '1.0.0',
1046
+ } as unknown as ChildProcess)
726
1047
  }
727
1048
 
728
1049
  private static fakeFetch() {
@@ -739,7 +1060,10 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
739
1060
  NpmAutopackage.pathExists = fakePathExists
740
1061
  resetCallsToPathExists()
741
1062
 
742
- setPathShouldExist(this.abstractPackageTestPath, false)
1063
+ setPathShouldExist(this.packageDir, false)
1064
+ setPathShouldExist(this.packageJsonPath, false)
1065
+ setPathShouldExist(this.tasksJsonPath, false)
1066
+ setPathShouldExist(this.abstractTestPath, false)
743
1067
  }
744
1068
 
745
1069
  private static fakeReadFile() {
@@ -752,6 +1076,13 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
752
1076
  this.tasksJsonPath,
753
1077
  JSON.stringify(this.originalTasksJson)
754
1078
  )
1079
+
1080
+ setFakeReadFileResult(
1081
+ this.tsconfigPath,
1082
+ JSON.stringify(this.originalTsconfig)
1083
+ )
1084
+
1085
+ setFakeReadFileResult(this.gitignorePath, this.originalGitignore)
755
1086
  }
756
1087
 
757
1088
  private static fakeWriteFile() {
@@ -773,39 +1104,24 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
773
1104
  setFakeFetchResponse(this.reposUrl, fakeResponse)
774
1105
  }
775
1106
 
776
- private static readonly installDir = this.generateId()
777
- private static readonly name = this.generateId()
778
- private static readonly description = this.generateId()
779
- private static readonly gitNamespace = this.generateId()
780
- private static readonly npmNamespace = this.generateId()
781
- private static readonly keywords = [this.generateId(), this.generateId()]
782
- private static readonly license = this.generateId()
783
- private static readonly author = this.generateId()
784
-
785
- private static readonly githubToken = this.generateId()
786
- private static readonly randomId = this.generateId()
787
-
788
1107
  private static get reposUrl() {
789
- return `https://api.github.com/repos/${this.gitNamespace}/${this.name}`
1108
+ return `https://api.github.com/repos/${this.gitNamespace}/${this.packageName}`
790
1109
  }
791
1110
 
792
1111
  private static get orgsUrl() {
793
1112
  return `https://api.github.com/orgs/${this.gitNamespace}/repos`
794
1113
  }
795
1114
 
796
- private static readonly dependencies = {
797
- [this.generateId()]: this.generateId(),
798
- [this.generateId()]: this.generateId(),
799
- }
800
-
801
1115
  private static get originalPackageJson() {
802
1116
  return JSON.stringify({
803
- name: this.name,
1117
+ name: this.packageName,
804
1118
  description: 'Old description',
805
1119
  dependencies: this.dependencies,
806
1120
  devDependencies: {
807
1121
  '@neurodevs/generate-id': '^1.0.0',
808
1122
  '@neurodevs/node-tdd': '^1.0.0',
1123
+ '@neurodevs/eslint-config-ndx': '^1.0.0',
1124
+ '@neurodevs/prettier-config-ndx': '^1.0.0',
809
1125
  },
810
1126
  })
811
1127
  }
@@ -815,23 +1131,62 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
815
1131
  ...JSON.parse(this.originalPackageJson),
816
1132
  name: this.scopedPackageName,
817
1133
  description: this.description,
1134
+ type: 'module',
818
1135
  keywords: this.keywords,
819
1136
  license: this.license,
820
1137
  author: this.author,
821
1138
  main: 'build/index.js',
822
- homepage: `https://github.com/${this.gitNamespace}/${this.name}`,
1139
+ homepage: `https://github.com/${this.gitNamespace}/${this.packageName}`,
823
1140
  repository: {
824
1141
  type: 'git',
825
- url: `git+https://github.com/${this.gitNamespace}/${this.name}.git`,
1142
+ url: `git+https://github.com/${this.gitNamespace}/${this.packageName}.git`,
826
1143
  },
827
1144
  bugs: {
828
- url: `https://github.com/${this.gitNamespace}/${this.name}/issues`,
1145
+ url: `https://github.com/${this.gitNamespace}/${this.packageName}/issues`,
829
1146
  },
830
1147
  dependencies: this.dependencies,
831
1148
  })
832
1149
  }
833
1150
 
834
- private static readonly tasksJsonPath = '.vscode/tasks.json'
1151
+ private static get originalTsconfig(): TsConfig {
1152
+ return {
1153
+ compilerOptions: {
1154
+ lib: [this.customLib],
1155
+ types: [this.customType],
1156
+ },
1157
+ include: [this.customInclude],
1158
+ customOption: this.customOption,
1159
+ }
1160
+ }
1161
+
1162
+ private static get updatedTsconfig() {
1163
+ return {
1164
+ ...this.originalTsconfig,
1165
+ compilerOptions: {
1166
+ module: 'nodenext',
1167
+ moduleResolution: 'nodenext',
1168
+ target: 'ES2022',
1169
+ lib: [this.customLib, 'ES2022'],
1170
+ types: [this.customType, 'node'],
1171
+ baseUrl: 'src',
1172
+ outDir: 'build',
1173
+ sourceMap: false,
1174
+ strict: true,
1175
+ noImplicitAny: true,
1176
+ noImplicitReturns: true,
1177
+ noUnusedLocals: true,
1178
+ forceConsistentCasingInFileNames: true,
1179
+ declaration: true,
1180
+ skipLibCheck: true,
1181
+ esModuleInterop: true,
1182
+ moduleDetection: 'force',
1183
+ allowJs: true,
1184
+ resolveJsonModule: true,
1185
+ experimentalDecorators: true,
1186
+ },
1187
+ include: [this.customInclude, './src/*.ts', './src/**/*.ts'],
1188
+ }
1189
+ }
835
1190
 
836
1191
  private static originalTasksJson = {
837
1192
  [this.randomId]: this.randomId,
@@ -881,32 +1236,6 @@ export default class NpmAutopackageTest extends AbstractPackageTest {
881
1236
  )
882
1237
  }
883
1238
 
884
- private static readonly yarnInstallDevDepsCommand =
885
- 'yarn add -D @neurodevs/generate-id@latest @neurodevs/node-tdd@latest'
886
-
887
- private static readonly abstractPackageTestPath =
888
- 'src/__tests__/AbstractPackageTest.ts'
889
-
890
- private static readonly abstractPackageTestFile = `import AbstractModuleTest from '@neurodevs/node-tdd'
891
-
892
- export default abstract class AbstractPackageTest extends AbstractModuleTest {
893
- protected static async beforeEach() {
894
- await super.beforeEach()
895
- }
896
- }
897
- `
898
-
899
- private static readonly defaultOptions = {
900
- installDir: this.installDir,
901
- name: this.name,
902
- description: this.description,
903
- gitNamespace: this.gitNamespace,
904
- npmNamespace: this.npmNamespace,
905
- keywords: this.keywords,
906
- license: this.license,
907
- author: this.author,
908
- }
909
-
910
1239
  private static NpmAutopackage(options?: Partial<AutopackageOptions>) {
911
1240
  return NpmAutopackage.Create({ ...this.defaultOptions, ...options })
912
1241
  }