@neurodevs/meta-node 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/build/__tests__/AbstractAutomoduleTest.d.ts +17 -0
  2. package/build/__tests__/AbstractAutomoduleTest.js +56 -0
  3. package/build/__tests__/AbstractAutomoduleTest.js.map +1 -0
  4. package/build/__tests__/modules/ImplAutomodule.test.d.ts +3 -13
  5. package/build/__tests__/modules/ImplAutomodule.test.js +15 -50
  6. package/build/__tests__/modules/ImplAutomodule.test.js.map +1 -1
  7. package/build/__tests__/modules/UiAutomodule.test.d.ts +16 -0
  8. package/build/__tests__/modules/UiAutomodule.test.js +168 -0
  9. package/build/__tests__/modules/UiAutomodule.test.js.map +1 -0
  10. package/build/index.d.ts +4 -0
  11. package/build/index.js +7 -1
  12. package/build/index.js.map +1 -1
  13. package/build/modules/AbstractAutomodule.d.ts +44 -0
  14. package/build/modules/AbstractAutomodule.js +79 -0
  15. package/build/modules/AbstractAutomodule.js.map +1 -0
  16. package/build/modules/ImplAutomodule.d.ts +10 -32
  17. package/build/modules/ImplAutomodule.js +20 -64
  18. package/build/modules/ImplAutomodule.js.map +1 -1
  19. package/build/modules/NpmAutopackage.d.ts +3 -3
  20. package/build/modules/NpmAutopackage.js +8 -7
  21. package/build/modules/NpmAutopackage.js.map +1 -1
  22. package/build/modules/UiAutomodule.d.ts +20 -0
  23. package/build/modules/UiAutomodule.js +123 -0
  24. package/build/modules/UiAutomodule.js.map +1 -0
  25. package/build/scripts/{runAutomodule.js → runImplAutomodule.js} +1 -1
  26. package/build/scripts/runImplAutomodule.js.map +1 -0
  27. package/build/scripts/runUiAutomodule.d.ts +1 -0
  28. package/build/scripts/runUiAutomodule.js +22 -0
  29. package/build/scripts/runUiAutomodule.js.map +1 -0
  30. package/build/testDoubles/Automodule/FakeAutomodule.d.ts +7 -4
  31. package/build/testDoubles/Automodule/FakeAutomodule.js +6 -6
  32. package/build/testDoubles/Automodule/FakeAutomodule.js.map +1 -1
  33. package/build/types.d.ts +8 -0
  34. package/build/types.js +3 -0
  35. package/build/types.js.map +1 -0
  36. package/package.json +2 -3
  37. package/src/__tests__/AbstractAutomoduleTest.ts +83 -0
  38. package/src/__tests__/modules/ImplAutomodule.test.ts +17 -78
  39. package/src/__tests__/modules/UiAutomodule.test.ts +174 -0
  40. package/src/index.ts +6 -0
  41. package/src/modules/AbstractAutomodule.ts +133 -0
  42. package/src/modules/ImplAutomodule.ts +32 -98
  43. package/src/modules/NpmAutopackage.ts +8 -7
  44. package/src/modules/UiAutomodule.ts +143 -0
  45. package/src/scripts/runUiAutomodule.ts +23 -0
  46. package/src/testDoubles/Automodule/FakeAutomodule.ts +10 -6
  47. package/src/types.ts +9 -0
  48. package/build/scripts/runAutomodule.js.map +0 -1
  49. /package/build/scripts/{runAutomodule.d.ts → runImplAutomodule.d.ts} +0 -0
  50. /package/src/scripts/{runAutomodule.ts → runImplAutomodule.ts} +0 -0
@@ -0,0 +1,83 @@
1
+ import { writeFile } from 'fs/promises'
2
+ import { assert, generateId } from '@sprucelabs/test-utils'
3
+ import {
4
+ fakePathExists,
5
+ fakeWriteFile,
6
+ resetCallsToPathExists,
7
+ resetCallsToWriteFile,
8
+ setPathShouldExist,
9
+ } from '@neurodevs/fake-node-core'
10
+ import AbstractAutomodule from '../modules/AbstractAutomodule'
11
+ import { Automodule } from '../types'
12
+ import AbstractPackageTest from './AbstractPackageTest'
13
+
14
+ export default class AbstractAutomoduleTest extends AbstractPackageTest {
15
+ protected static instance: Automodule
16
+
17
+ protected static async beforeEach() {
18
+ await super.beforeEach()
19
+
20
+ this.setFakePathExists()
21
+ this.setFakeWriteFile()
22
+ }
23
+
24
+ protected static async runAbstractTests() {
25
+ await this.runThrowsIfTestSaveDirMissing()
26
+ await this.runThrowsIfModuleSaveDirMissing()
27
+ await this.runThrowsIfFakeSaveDirMissing()
28
+ }
29
+
30
+ protected static async runThrowsIfTestSaveDirMissing() {
31
+ setPathShouldExist(this.testSaveDir, false)
32
+
33
+ await assert.doesThrowAsync(
34
+ async () => await this.run(),
35
+ `testSaveDir does not exist: ${this.testSaveDir}!`
36
+ )
37
+ }
38
+
39
+ protected static async runThrowsIfModuleSaveDirMissing() {
40
+ setPathShouldExist(this.testSaveDir, true)
41
+ setPathShouldExist(this.moduleSaveDir, false)
42
+
43
+ await assert.doesThrowAsync(
44
+ async () => await this.run(),
45
+ `moduleSaveDir does not exist: ${this.moduleSaveDir}!`
46
+ )
47
+ }
48
+
49
+ protected static async runThrowsIfFakeSaveDirMissing() {
50
+ setPathShouldExist(this.moduleSaveDir, true)
51
+ setPathShouldExist(this.fakeSaveDir, false)
52
+
53
+ await assert.doesThrowAsync(
54
+ async () => await this.run(),
55
+ `fakeSaveDir does not exist: ${this.fakeSaveDir}!`
56
+ )
57
+ }
58
+
59
+ protected static async run() {
60
+ return this.instance.run()
61
+ }
62
+
63
+ protected static readonly testSaveDir = generateId()
64
+ protected static readonly moduleSaveDir = generateId()
65
+ protected static readonly fakeSaveDir = generateId()
66
+ protected static readonly indexFilePath = './src/index.ts'
67
+
68
+ protected static setFakePathExists() {
69
+ AbstractAutomodule.pathExists = fakePathExists
70
+
71
+ setPathShouldExist(this.testSaveDir, true)
72
+ setPathShouldExist(this.moduleSaveDir, true)
73
+ setPathShouldExist(this.fakeSaveDir, true)
74
+ setPathShouldExist(this.indexFilePath, true)
75
+
76
+ resetCallsToPathExists()
77
+ }
78
+
79
+ protected static setFakeWriteFile() {
80
+ AbstractAutomodule.writeFile = fakeWriteFile as typeof writeFile
81
+ resetCallsToWriteFile()
82
+ }
83
+ }
@@ -1,81 +1,40 @@
1
1
  import { exec as execSync } from 'child_process'
2
- import { readFile, writeFile } from 'fs/promises'
2
+ import { readFile } from 'fs/promises'
3
3
  import { promisify } from 'util'
4
4
  import { test, assert, generateId } from '@sprucelabs/test-utils'
5
5
  import {
6
6
  callsToExec,
7
7
  callsToWriteFile,
8
8
  fakeExec,
9
- fakePathExists,
10
9
  fakeReadFile,
11
10
  fakeReadFileResult,
12
- fakeWriteFile,
11
+ resetCallsToExec,
13
12
  resetCallsToReadFile,
14
- resetCallsToWriteFile,
15
13
  setFakeReadFileResult,
16
- setPathShouldExist,
17
14
  } from '@neurodevs/fake-node-core'
18
- import ImplAutomodule, { Automodule } from '../../modules/ImplAutomodule'
19
- import AbstractPackageTest from '../AbstractPackageTest'
15
+ import ImplAutomodule from '../../modules/ImplAutomodule'
16
+ import AbstractAutomoduleTest from '../AbstractAutomoduleTest'
20
17
 
21
18
  const exec = promisify(execSync)
22
19
 
23
- export default class ImplAutomoduleTest extends AbstractPackageTest {
24
- private static instance: Automodule
25
-
20
+ export default class ImplAutomoduleTest extends AbstractAutomoduleTest {
26
21
  protected static async beforeEach() {
27
22
  await super.beforeEach()
28
23
 
29
24
  this.setFakeExec()
30
- this.setFakePathExists()
31
25
  this.setFakeReadFile()
32
- this.setFakeWriteFile()
33
26
 
34
27
  this.instance = this.ImplAutomodule()
35
28
  }
36
29
 
37
30
  @test()
38
- protected static async createsInstance() {
39
- assert.isTruthy(this.instance, 'Failed to create instance!')
40
- }
41
-
42
- @test()
43
- protected static async runThrowsIfTestSaveDirMissing() {
44
- setPathShouldExist(this.testSaveDir, false)
45
-
46
- const err = await assert.doesThrowAsync(async () => await this.run())
47
-
48
- assert.isEqual(
49
- err.message,
50
- `testSaveDir does not exist: ${this.testSaveDir}!`,
51
- 'Did not receive the expected error!'
52
- )
31
+ protected static async passesAbstractTests() {
32
+ await this.runAbstractTests()
53
33
  }
54
34
 
55
35
  @test()
56
- protected static async runThrowsIfModuleSaveDirMissing() {
57
- setPathShouldExist(this.moduleSaveDir, false)
58
-
59
- const err = await assert.doesThrowAsync(async () => await this.run())
60
-
61
- assert.isEqual(
62
- err.message,
63
- `moduleSaveDir does not exist: ${this.moduleSaveDir}!`,
64
- 'Did not receive the expected error!'
65
- )
66
- }
67
-
68
- @test()
69
- protected static async runThrowsIfFakeSaveDirMissing() {
70
- setPathShouldExist(this.fakeSaveDir, false)
71
-
72
- const err = await assert.doesThrowAsync(async () => await this.run())
73
-
74
- assert.isEqual(
75
- err.message,
76
- `fakeSaveDir does not exist: ${this.fakeSaveDir}!`,
77
- 'Did not receive the expected error!'
78
- )
36
+ protected static async createsInstance() {
37
+ assert.isTruthy(this.instance, 'Failed to create instance!')
79
38
  }
80
39
 
81
40
  @test()
@@ -83,11 +42,13 @@ export default class ImplAutomoduleTest extends AbstractPackageTest {
83
42
  await this.run()
84
43
 
85
44
  assert.isEqualDeep(
86
- callsToWriteFile[0],
45
+ {
46
+ file: callsToWriteFile[0].file,
47
+ data: this.normalize(callsToWriteFile[0].data),
48
+ },
87
49
  {
88
50
  file: `${this.testSaveDir}/${this.implName}.test.ts`,
89
- data: this.testFilePattern,
90
- options: undefined,
51
+ data: this.normalize(this.testFilePattern),
91
52
  },
92
53
  'Did not write expected test file!'
93
54
  )
@@ -159,21 +120,9 @@ export default class ImplAutomoduleTest extends AbstractPackageTest {
159
120
  )
160
121
  }
161
122
 
162
- private static async run() {
163
- return await this.instance.run()
164
- }
165
-
166
123
  private static setFakeExec() {
167
124
  ImplAutomodule.exec = fakeExec as unknown as typeof exec
168
- }
169
-
170
- private static setFakePathExists() {
171
- ImplAutomodule.pathExists = fakePathExists
172
-
173
- setPathShouldExist(this.testSaveDir, true)
174
- setPathShouldExist(this.moduleSaveDir, true)
175
- setPathShouldExist(this.fakeSaveDir, true)
176
- setPathShouldExist(this.indexFilePath, true)
125
+ resetCallsToExec()
177
126
  }
178
127
 
179
128
  private static setFakeReadFile() {
@@ -181,17 +130,9 @@ export default class ImplAutomoduleTest extends AbstractPackageTest {
181
130
  resetCallsToReadFile()
182
131
  }
183
132
 
184
- private static setFakeWriteFile() {
185
- ImplAutomodule.writeFile = fakeWriteFile as typeof writeFile
186
- resetCallsToWriteFile()
187
- }
188
133
  private static readonly interfaceName = `B-${generateId()}`
189
134
  private static readonly implName = generateId()
190
135
 
191
- private static readonly testSaveDir = generateId()
192
- private static readonly moduleSaveDir = generateId()
193
- private static readonly fakeSaveDir = generateId()
194
-
195
136
  private static get testFilePattern() {
196
137
  return `
197
138
  import AbstractSpruceTest, { test, assert } from '@sprucelabs/test-utils'
@@ -199,10 +140,10 @@ export default class ImplAutomoduleTest extends AbstractPackageTest {
199
140
 
200
141
  export default class ${this.implName}Test extends AbstractSpruceTest {
201
142
  private static instance: ${this.interfaceName}
202
-
143
+
203
144
  protected static async beforeEach() {
204
145
  await super.beforeEach()
205
-
146
+
206
147
  this.instance = this.${this.implName}()
207
148
  }
208
149
 
@@ -254,8 +195,6 @@ export default class ImplAutomoduleTest extends AbstractPackageTest {
254
195
  `
255
196
  }
256
197
 
257
- private static readonly indexFilePath = './src/index.ts'
258
-
259
198
  private static get indexFilePattern() {
260
199
  return `
261
200
  ${fakeReadFileResult}
@@ -0,0 +1,174 @@
1
+ import { test, assert, generateId } from '@sprucelabs/test-utils'
2
+ import { callsToWriteFile } from '@neurodevs/fake-node-core'
3
+ import UiAutomodule from '../../modules/UiAutomodule'
4
+ import AbstractAutomoduleTest from '../AbstractAutomoduleTest'
5
+
6
+ export default class UiAutomoduleTest extends AbstractAutomoduleTest {
7
+ protected static async beforeEach() {
8
+ await super.beforeEach()
9
+
10
+ this.instance = this.UiAutomodule()
11
+ }
12
+
13
+ @test()
14
+ protected static async passesAbstractTests() {
15
+ await this.runAbstractTests()
16
+ }
17
+
18
+ @test()
19
+ protected static async createsInstance() {
20
+ assert.isTruthy(this.instance, 'Failed to create instance!')
21
+ }
22
+
23
+ @test()
24
+ protected static async createsTestFileAsExpected() {
25
+ await this.run()
26
+
27
+ assert.isEqualDeep(
28
+ callsToWriteFile[0],
29
+ {
30
+ file: `${this.testSaveDir}/${this.componentName}.test.tsx`,
31
+ data: this.testFilePattern,
32
+ options: undefined,
33
+ },
34
+ 'Did not write expected test file!'
35
+ )
36
+ }
37
+
38
+ @test()
39
+ protected static async createsModuleFileAsExpected() {
40
+ await this.run()
41
+
42
+ assert.isEqualDeep(
43
+ callsToWriteFile[1],
44
+ {
45
+ file: `${this.moduleSaveDir}/${this.componentName}.tsx`,
46
+ data: this.moduleFilePattern,
47
+ options: undefined,
48
+ },
49
+ 'Did not write expected module file!'
50
+ )
51
+ }
52
+
53
+ @test()
54
+ protected static async createsFakeFileAsExpected() {
55
+ await this.run()
56
+
57
+ assert.isEqualDeep(
58
+ callsToWriteFile[2],
59
+ {
60
+ file: `${this.fakeSaveDir}/Fake${this.componentName}.tsx`,
61
+ data: this.fakeFilePattern,
62
+ options: undefined,
63
+ },
64
+ 'Did not write expected module file!'
65
+ )
66
+ }
67
+
68
+ private static readonly componentName = generateId()
69
+
70
+ private static readonly componentNameKebabCase = this.toKebabCase(
71
+ this.componentName
72
+ )
73
+
74
+ private static get testFilePattern() {
75
+ return `
76
+ import { test, assert } from '@sprucelabs/test-utils'
77
+ import { render, RenderResult } from '@testing-library/react'
78
+ import ${this.componentName} from '../../ui/${this.componentName}'
79
+ import AbstractPackageTest from '../AbstractPackageTest'
80
+
81
+ export default class ${this.componentName}Test extends AbstractPackageTest {
82
+ private static result: RenderResult
83
+
84
+ protected static async beforeEach() {
85
+ await super.beforeEach()
86
+
87
+ this.result = this.render()
88
+ }
89
+
90
+ @test()
91
+ protected static async rendersComponent() {
92
+ assert.isTruthy(this.result, 'Failed to render component!')
93
+ }
94
+
95
+ @test()
96
+ protected static async rendersTopLevelDivWithExpectedClass() {
97
+ assert.isEqual(
98
+ this.div.className,
99
+ this.className,
100
+ 'Incorrect class for top-level div!'
101
+ )
102
+ }
103
+
104
+ private static get div() {
105
+ return this.getByTestId(this.className)
106
+ }
107
+
108
+ private static get getByTestId() {
109
+ return this.result.getByTestId
110
+ }
111
+
112
+ private static readonly className = '${this.componentNameKebabCase}'
113
+
114
+ protected static render() {
115
+ return render(<${this.componentName} />)
116
+ }
117
+ }
118
+ `
119
+ }
120
+
121
+ private static get moduleFilePattern() {
122
+ return `
123
+ import React from 'react'
124
+
125
+ const ${this.componentName}: React.FC = () => {
126
+ return (
127
+ <div
128
+ className="${this.componentNameKebabCase}"
129
+ data-testid="${this.componentNameKebabCase}"
130
+ />
131
+ )
132
+ }
133
+
134
+ export default ${this.componentName}
135
+ `
136
+ }
137
+
138
+ private static get fakeFilePattern() {
139
+ return `
140
+ import React from 'react'
141
+ import { ${this.componentName}Props } from '../ui/${this.componentName}'
142
+
143
+ export let last${this.componentName}Props: ${this.componentName}Props | undefined
144
+
145
+ const Fake${this.componentName}: React.FC<${this.componentName}Props> = (
146
+ props: ${this.componentName}Props
147
+ ) => {
148
+ last${this.componentName}Props = props
149
+
150
+ return (
151
+ <div data-testid="${this.componentNameKebabCase}" />
152
+ )
153
+ }
154
+
155
+ export default Fake${this.componentName}
156
+ `
157
+ }
158
+
159
+ private static toKebabCase(str: string): string {
160
+ return str
161
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
162
+ .replace(/[\s_]+/g, '-')
163
+ .toLowerCase()
164
+ }
165
+
166
+ private static UiAutomodule() {
167
+ return UiAutomodule.Create({
168
+ testSaveDir: this.testSaveDir,
169
+ moduleSaveDir: this.moduleSaveDir,
170
+ fakeSaveDir: this.fakeSaveDir,
171
+ componentName: this.componentName,
172
+ })
173
+ }
174
+ }
package/src/index.ts CHANGED
@@ -16,9 +16,15 @@ export * from './testDoubles/Autodocumenter/FakeAutodocumenter'
16
16
 
17
17
  // Automodule
18
18
 
19
+ export { default as AbstractAutomodule } from './modules/AbstractAutomodule'
20
+ export * from './modules/AbstractAutomodule'
21
+
19
22
  export { default as ImplAutomodule } from './modules/ImplAutomodule'
20
23
  export * from './modules/ImplAutomodule'
21
24
 
25
+ export { default as UiAutomodule } from './modules/UiAutomodule'
26
+ export * from './modules/UiAutomodule'
27
+
22
28
  export { default as FakeAutomodule } from './testDoubles/Automodule/FakeAutomodule'
23
29
  export * from './testDoubles/Automodule/FakeAutomodule'
24
30
 
@@ -0,0 +1,133 @@
1
+ import { writeFile } from 'fs/promises'
2
+ import { pathExists } from 'fs-extra'
3
+ import { Automodule, BaseAutomoduleOptions } from '../types'
4
+
5
+ export default abstract class AbstractAutomodule implements Automodule {
6
+ public static pathExists = pathExists
7
+ public static writeFile = writeFile
8
+
9
+ protected testSaveDir: string
10
+ protected moduleSaveDir: string
11
+ protected fakeSaveDir: string
12
+
13
+ protected testFileName!: string
14
+ protected testFileContent!: string
15
+ protected moduleFileName!: string
16
+ protected moduleFileContent!: string
17
+ protected fakeFileName!: string
18
+ protected fakeFileContent!: string
19
+
20
+ protected constructor(options: BaseAutomoduleOptions) {
21
+ const { testSaveDir, moduleSaveDir, fakeSaveDir } = options
22
+
23
+ this.testSaveDir = testSaveDir
24
+ this.moduleSaveDir = moduleSaveDir
25
+ this.fakeSaveDir = fakeSaveDir
26
+ }
27
+
28
+ public abstract run(): Promise<void>
29
+
30
+ protected async runAbstract(options: AbstractAutomoduleRunOptions) {
31
+ const {
32
+ testFileName,
33
+ testFileContent,
34
+ moduleFileName,
35
+ moduleFileContent,
36
+ fakeFileName,
37
+ fakeFileContent,
38
+ } = options
39
+
40
+ this.testFileName = testFileName
41
+ this.testFileContent = testFileContent
42
+ this.moduleFileName = moduleFileName
43
+ this.moduleFileContent = moduleFileContent
44
+ this.fakeFileName = fakeFileName
45
+ this.fakeFileContent = fakeFileContent
46
+
47
+ await this.throwIfDirectoriesDoNotExist()
48
+
49
+ await this.createTestFile()
50
+ await this.createModuleFile()
51
+ await this.createFakeFile()
52
+ }
53
+
54
+ private async throwIfDirectoriesDoNotExist() {
55
+ await this.throwIfTestDirDoesNotExist()
56
+ await this.throwIfModuleDirDoesNotExist()
57
+ await this.throwIfFakeDirDoesNotExist()
58
+ }
59
+
60
+ private async throwIfTestDirDoesNotExist() {
61
+ const testDirExists = await this.pathExists(this.testSaveDir)
62
+
63
+ if (!testDirExists) {
64
+ this.throw(`testSaveDir does not exist: ${this.testSaveDir}!`)
65
+ }
66
+ }
67
+
68
+ private async throwIfModuleDirDoesNotExist() {
69
+ const moduleDirExists = await this.pathExists(this.moduleSaveDir)
70
+
71
+ if (!moduleDirExists) {
72
+ this.throw(`moduleSaveDir does not exist: ${this.moduleSaveDir}!`)
73
+ }
74
+ }
75
+
76
+ private async throwIfFakeDirDoesNotExist() {
77
+ const fakeDirExists = await this.pathExists(this.fakeSaveDir)
78
+
79
+ if (!fakeDirExists) {
80
+ this.throw(`fakeSaveDir does not exist: ${this.fakeSaveDir}!`)
81
+ }
82
+ }
83
+
84
+ private throw(err: string) {
85
+ throw new Error(err)
86
+ }
87
+
88
+ private async createTestFile() {
89
+ await this.writeFile(this.testFilePath, this.testFileContent)
90
+ }
91
+
92
+ private get testFilePath() {
93
+ return `${this.testSaveDir}/${this.testFileName}`
94
+ }
95
+
96
+ private async createModuleFile() {
97
+ await this.writeFile(this.moduleFilePath, this.moduleFileContent)
98
+ }
99
+
100
+ private get moduleFilePath() {
101
+ return `${this.moduleSaveDir}/${this.moduleFileName}`
102
+ }
103
+
104
+ private async createFakeFile() {
105
+ await this.writeFile(this.fakeFilePath, this.fakeFileContent)
106
+ }
107
+
108
+ private get fakeFilePath() {
109
+ return `${this.fakeSaveDir}/${this.fakeFileName}`
110
+ }
111
+
112
+ private get pathExists() {
113
+ return AbstractAutomodule.pathExists
114
+ }
115
+
116
+ protected get writeFile() {
117
+ return AbstractAutomodule.writeFile
118
+ }
119
+ }
120
+
121
+ export interface AbstractAutomoduleOptions extends BaseAutomoduleOptions {
122
+ testFileName: string
123
+ testFileContent: string
124
+ }
125
+
126
+ export interface AbstractAutomoduleRunOptions {
127
+ testFileName: string
128
+ testFileContent: string
129
+ moduleFileName: string
130
+ moduleFileContent: string
131
+ fakeFileName: string
132
+ fakeFileContent: string
133
+ }