@sprucelabs/spruce-cli 19.1.4 → 19.1.6

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 (44) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/__tests__/behavioral/schemas/SettingUpSchemasForModuleDistribution.test.js +1 -2
  3. package/build/__tests__/behavioral/schemas/SettingUpSchemasForModuleDistribution.test.js.map +1 -1
  4. package/build/__tests__/behavioral/tests/CreatingATest.test.d.ts +0 -2
  5. package/build/__tests__/behavioral/tests/CreatingATest.test.js +75 -147
  6. package/build/__tests__/behavioral/tests/CreatingATest.test.js.map +1 -1
  7. package/build/__tests__/behavioral/tests/RunningTests.test.d.ts +3 -0
  8. package/build/__tests__/behavioral/tests/RunningTests.test.js +99 -43
  9. package/build/__tests__/behavioral/tests/RunningTests.test.js.map +1 -1
  10. package/build/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.js +3 -1
  11. package/build/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.js.map +1 -1
  12. package/build/__tests__/implementation/TestRunner.test.d.ts +1 -0
  13. package/build/__tests__/implementation/TestRunner.test.js +22 -10
  14. package/build/__tests__/implementation/TestRunner.test.js.map +1 -1
  15. package/build/features/test/actions/CreateAction.js +13 -29
  16. package/build/features/test/actions/CreateAction.js.map +1 -1
  17. package/build/features/vscode/VsCodeFeature.js +1 -1
  18. package/build/features/vscode/VsCodeFeature.js.map +1 -1
  19. package/build/interfaces/SpyInterface.d.ts +6 -1
  20. package/build/interfaces/SpyInterface.js +1 -1
  21. package/build/interfaces/SpyInterface.js.map +1 -1
  22. package/build/interfaces/TerminalInterface.js +3 -1
  23. package/build/interfaces/TerminalInterface.js.map +1 -1
  24. package/build/tests/utilities/uiAssert.utility.d.ts +1 -0
  25. package/build/tests/utilities/uiAssert.utility.js +9 -0
  26. package/build/tests/utilities/uiAssert.utility.js.map +1 -1
  27. package/build/widgets/types/window.types.js +2 -0
  28. package/build/widgets/types/window.types.js.map +1 -1
  29. package/node_modules/@typescript-eslint/parser/dist/parser.d.ts.map +1 -1
  30. package/node_modules/@typescript-eslint/parser/dist/parser.js +5 -1
  31. package/node_modules/@typescript-eslint/parser/dist/parser.js.map +1 -1
  32. package/node_modules/@typescript-eslint/parser/package.json +5 -5
  33. package/node_modules/@typescript-eslint/scope-manager/package.json +5 -5
  34. package/node_modules/@typescript-eslint/types/package.json +2 -2
  35. package/node_modules/@typescript-eslint/typescript-estree/package.json +4 -4
  36. package/node_modules/@typescript-eslint/visitor-keys/package.json +3 -3
  37. package/package.json +30 -30
  38. package/src/__tests__/behavioral/tests/CreatingATest.test.ts +8 -47
  39. package/src/__tests__/behavioral/tests/RunningTests.test.ts +34 -14
  40. package/src/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.ts +2 -2
  41. package/src/__tests__/implementation/TestRunner.test.ts +9 -0
  42. package/src/features/test/actions/CreateAction.ts +13 -32
  43. package/src/interfaces/SpyInterface.ts +15 -3
  44. package/src/tests/utilities/uiAssert.utility.ts +9 -0
@@ -59,33 +59,12 @@ export default class CreatingBehavioralTestsTest extends AbstractTestTest {
59
59
  testType
60
60
  )
61
61
 
62
- uiAssert.assertSelectRenderChoice(this.ui, '.', testType)
63
- uiAssert.assertSelectRenderChoice(this.ui, `dummy1`, `${testType}/dummy1`)
64
-
65
- await this.ui.sendInput('.')
66
- await this.waitAndSelectSubClass()
67
-
68
- await promise
69
- }
70
-
71
- @test()
72
- protected static async listsManyDirsIfExistInsideTestDir() {
73
- await this.installTests()
74
-
75
- const dirs = ['dir1', 'dir2', 'dir3']
76
-
77
- for (const dir of dirs) {
78
- this.createTestSubDir('behavioral', dir)
79
- }
80
-
81
- const { promise } = await this.installAndStartTestActionAndWaitForInput()
82
-
83
- for (const dir of dirs) {
84
- uiAssert.assertSelectRenderChoice(this.ui, `${dir}`, `behavioral/${dir}`)
85
- }
86
-
87
- await this.ui.sendInput('.')
62
+ uiAssert.assertRendersDirectorySelect(
63
+ this.ui,
64
+ this.resolvePath('src', '__tests__', testType)
65
+ )
88
66
 
67
+ await this.ui.sendInput('')
89
68
  await this.waitAndSelectSubClass()
90
69
 
91
70
  await promise
@@ -95,13 +74,13 @@ export default class CreatingBehavioralTestsTest extends AbstractTestTest {
95
74
  @test('can select sub dir 2', 'test-2')
96
75
  protected static async selectingAnOptionRendersToSubDir(dirName: string) {
97
76
  await this.installTests()
98
- this.createTestSubDir('behavioral', dirName)
77
+ const dir = this.createTestSubDir('behavioral', dirName)
99
78
 
100
79
  const { promise } = await this.installAndStartTestActionAndWaitForInput(
101
80
  'behavioral'
102
81
  )
103
82
 
104
- await this.ui.sendInput(`${dirName}`)
83
+ await this.ui.sendInput({ path: dir })
105
84
 
106
85
  await this.waitAndSelectSubClass()
107
86
 
@@ -118,25 +97,6 @@ export default class CreatingBehavioralTestsTest extends AbstractTestTest {
118
97
  assert.isEqual(expectedPath, results.files?.[0]?.path)
119
98
  }
120
99
 
121
- @test()
122
- protected static async doesNotListFiles() {
123
- await this.installTests()
124
- this.createTestSubDir('behavioral', 'subdir')
125
-
126
- const file = this.resolveTestDir('behavioral', 'test.ts')
127
- diskUtil.writeFile(file, 'what the!?')
128
-
129
- await this.installAndStartTestActionAndWaitForInput()
130
-
131
- uiAssert.assertSelectDidNotRenderChoice(
132
- this.ui,
133
- 'test',
134
- `behavioral/test/test.ts`
135
- )
136
-
137
- this.ui.reset()
138
- }
139
-
140
100
  @test()
141
101
  protected static async allTestsComeFakedToStart() {
142
102
  const testFile = await this.createTestAndGetFile()
@@ -147,6 +107,7 @@ export default class CreatingBehavioralTestsTest extends AbstractTestTest {
147
107
  private static createTestSubDir(...testDirs: string[]) {
148
108
  const newDir = this.resolveTestDir(...testDirs)
149
109
  diskUtil.createDir(newDir)
110
+ return newDir
150
111
  }
151
112
 
152
113
  private static resolveTestDir(...testDirs: string[]) {
@@ -3,6 +3,13 @@ import { errorAssert } from '@sprucelabs/test-utils'
3
3
  import AbstractTestTest from '../../../tests/AbstractTestTest'
4
4
 
5
5
  export default class RunningTestsTest extends AbstractTestTest {
6
+ private static hasCreatedTest: any
7
+
8
+ protected static async beforeEach(): Promise<void> {
9
+ await super.beforeEach()
10
+ this.hasCreatedTest = false
11
+ }
12
+
6
13
  @test()
7
14
  protected static async hasTestAction() {
8
15
  await this.Cli()
@@ -12,35 +19,24 @@ export default class RunningTestsTest extends AbstractTestTest {
12
19
  @test()
13
20
  protected static async runningTestsActuallyRunsTests() {
14
21
  await this.installTests()
15
- const creationPromise = this.Action('test', 'create').execute({
16
- type: 'behavioral',
22
+
23
+ const creationResults = await this.createTest({
17
24
  nameReadable: 'Can book appointment',
18
25
  nameCamel: 'canBookAppointment',
19
26
  namePascal: 'CanBookAppointment',
20
27
  })
21
28
 
22
- await this.waitForInput()
23
- await this.ui.sendInput('')
24
-
25
- const creationResults = await creationPromise
26
-
27
29
  const file = creationResults.files?.[0]
28
30
  assert.isTruthy(file)
29
31
 
30
32
  this.fixBadTest(file.path)
31
33
 
32
- const promise = this.Action('test', 'create').execute({
33
- type: 'behavioral',
34
+ await this.createTest({
34
35
  nameReadable: 'Can cancel appointment',
35
36
  nameCamel: 'canCancelAppointment',
36
37
  namePascal: 'CanCancelAppointment',
37
38
  })
38
39
 
39
- await this.waitForInput()
40
- await this.ui.sendInput('')
41
-
42
- await promise
43
-
44
40
  await this.Service('build').build()
45
41
 
46
42
  const results = await this.Action('test', 'test').execute({
@@ -66,4 +62,28 @@ export default class RunningTestsTest extends AbstractTestTest {
66
62
  totalTodo: 0,
67
63
  })
68
64
  }
65
+
66
+ private static async createTest(options: {
67
+ nameReadable: string
68
+ nameCamel: string
69
+ namePascal: string
70
+ }) {
71
+ const creationPromise = this.Action('test', 'create').execute({
72
+ type: 'behavioral',
73
+ ...options,
74
+ })
75
+
76
+ if (this.hasCreatedTest) {
77
+ await this.waitForInput()
78
+ await this.ui.sendInput({ path: '.' })
79
+ }
80
+
81
+ this.hasCreatedTest = true
82
+
83
+ await this.waitForInput()
84
+ await this.ui.sendInput('')
85
+
86
+ const creationResults = await creationPromise
87
+ return creationResults
88
+ }
69
89
  }
@@ -42,14 +42,14 @@ export default class SelectingAnAbstractTestClassTest extends AbstractTestTest {
42
42
  @test()
43
43
  protected static async canSelectAbstractClassWhileSelectingSubDir() {
44
44
  const testDir = this.resolvePath('src', '__tests__', 'behavioral', 'taco')
45
+
45
46
  diskUtil.createDir(testDir)
46
47
 
47
48
  await this.installAndCopyTestFiles()
48
49
 
49
50
  const { promise } = await this.invokeCreateActionAndWaitForInput()
50
51
 
51
- await this.ui.sendInput('taco')
52
-
52
+ await this.ui.sendInput({ path: 'taco' })
53
53
  await this.waitForInput()
54
54
 
55
55
  this.selectOptionBasedOnLabel('AbstractBananaTestDifferentThanFileName')
@@ -8,9 +8,11 @@ import { CliInterface } from '../../types/cli.types'
8
8
 
9
9
  export default class TestRunnerTest extends AbstractTestTest {
10
10
  protected static testRunner: TestRunner
11
+ private static hasCreatedTest: boolean
11
12
 
12
13
  protected static async beforeEach() {
13
14
  await super.beforeEach()
15
+ this.hasCreatedTest = false
14
16
  this.testRunner = new TestRunner({
15
17
  cwd: this.cwd,
16
18
  commandService: this.Service('command'),
@@ -143,6 +145,13 @@ export default class TestRunnerTest extends AbstractTestTest {
143
145
  })
144
146
 
145
147
  await this.waitForInput()
148
+ if (this.hasCreatedTest) {
149
+ await this.ui.sendInput('')
150
+ await this.waitForInput()
151
+ }
152
+
153
+ this.hasCreatedTest = true
154
+
146
155
  await this.ui.sendInput('')
147
156
 
148
157
  const results = await promise
@@ -38,10 +38,7 @@ export default class CreateAction extends AbstractAction<OptionsSchema> {
38
38
  const candidates = await testFeature.buildParentClassCandidates()
39
39
 
40
40
  if (diskUtil.doesDirExist(resolvedDestination)) {
41
- resolvedDestination = await this.promptForSubDir(
42
- resolvedDestination,
43
- type
44
- )
41
+ resolvedDestination = await this.promptForSubDir(resolvedDestination)
45
42
  }
46
43
 
47
44
  if (candidates.length > 0) {
@@ -70,34 +67,18 @@ export default class CreateAction extends AbstractAction<OptionsSchema> {
70
67
  hints: ["run `spruce test` in your skill when you're ready!"],
71
68
  }
72
69
  }
73
- private async promptForSubDir(resolvedDestination: string, type: string) {
74
- const subdirs = diskUtil
75
- .readDir(resolvedDestination)
76
- .filter((d) =>
77
- diskUtil.isDir(diskUtil.resolvePath(resolvedDestination, d))
78
- )
79
-
80
- if (subdirs.length > 0) {
81
- const match = await this.ui.prompt({
82
- type: 'select',
83
- label: 'Where should I write this test?',
84
- isRequired: true,
85
- options: {
86
- choices: [
87
- {
88
- value: '.',
89
- label: `${type}`,
90
- },
91
- ...subdirs.map((dir) => ({
92
- value: `${dir}`,
93
- label: `${type}/${dir}`,
94
- })),
95
- ],
96
- },
97
- })
98
-
99
- resolvedDestination = diskUtil.resolvePath(resolvedDestination, match)
100
- }
70
+ private async promptForSubDir(resolvedDestination: string) {
71
+ const match = await this.ui.prompt({
72
+ type: 'directory',
73
+ label: 'Where should I write this test?',
74
+ isRequired: true,
75
+ defaultValue: {
76
+ path: diskUtil.resolvePath(resolvedDestination),
77
+ },
78
+ })
79
+
80
+ resolvedDestination = diskUtil.resolvePath(resolvedDestination, match.path)
81
+
101
82
  return resolvedDestination
102
83
  }
103
84
 
@@ -91,11 +91,17 @@ export default class SpyInterface implements GraphicsInterface {
91
91
  return this.invocations[this.invocations.length - 1]
92
92
  }
93
93
 
94
- public async sendInput(input: string | string[]): Promise<void> {
94
+ public async sendInput(input: Input): Promise<void> {
95
95
  this.trackInvocation('sendInput', input)
96
96
 
97
97
  this.optionallyRenderLine(
98
- `Sending input: "${input.length > 0 ? input : 'ENTER'}"`
98
+ `Sending input: "${
99
+ (input as FilePromptInput).path
100
+ ? (input as FilePromptInput).path
101
+ : (input as string).length > 0
102
+ ? input
103
+ : 'ENTER'
104
+ }"`
99
105
  )
100
106
 
101
107
  if (this.waitForEnterResolver) {
@@ -114,7 +120,7 @@ export default class SpyInterface implements GraphicsInterface {
114
120
 
115
121
  resolver(
116
122
  input === '\n' ||
117
- input.length === 0 ||
123
+ (input as string).length === 0 ||
118
124
  (typeof input === 'string' && input.toLowerCase() === 'y')
119
125
  )
120
126
  } else {
@@ -360,3 +366,9 @@ export default class SpyInterface implements GraphicsInterface {
360
366
  this.trackInvocation('clearBelowCursor')
361
367
  }
362
368
  }
369
+
370
+ type FilePromptInput = {
371
+ path: string
372
+ }
373
+
374
+ type Input = string | string[] | FilePromptInput
@@ -36,6 +36,15 @@ const uiAssert = {
36
36
  })
37
37
  },
38
38
 
39
+ assertRendersDirectorySelect(ui: SpyInterface, defaultValue: string) {
40
+ const last = ui.getLastInvocation()
41
+
42
+ assert.doesInclude(last.options, {
43
+ type: 'directory',
44
+ defaultValue: { path: defaultValue },
45
+ })
46
+ },
47
+
39
48
  async assertRendersConfirmWriteFile(ui: SpyInterface) {
40
49
  await ui.waitForInput()
41
50