@@ -18,68 +18,104 @@ import { zWorkspaceGetPackages } from "@zenflux/cli/src/core/workspace";
18
18
import { runCLI } from "@jest/core" ;
19
19
20
20
import type { Config } from "@jest/types" ;
21
-
22
- const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
23
-
24
- const rootPkg = new Package ( path . dirname ( zFindRootPackageJsonPath ( ) ) ) ;
25
-
26
- const filterProjects : string [ ] = [ ] ;
21
+ import type { DZJestProjectConfigInterface } from "@zenflux/jest/definitions" ;
27
22
28
23
if ( process . argv . includes ( "--help" ) || process . argv . includes ( "-h" ) ) {
29
24
ConsoleManager . $ . log ( "Use jest --help" ) ;
30
25
process . exit ( 0 ) ;
31
26
}
32
27
33
- if ( process . argv . includes ( "--selectedProjects" ) ) {
34
- const selectedProjectsKey = process . argv . indexOf ( "--selectedProjects" ) ;
35
- const selectedProjects = process . argv [ selectedProjectsKey + 1 ] ;
28
+ const currentDirPath = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
36
29
37
- if ( ! selectedProjects ) {
38
- ConsoleManager . $ . log ( "Use @z-jest --selectedProjects <project1, project2>" ) ;
39
- process . exit ( 1 ) ;
40
- }
41
-
42
- // Remove both key and value
43
- process . argv . splice ( selectedProjectsKey , 2 ) ;
30
+ const rootPkg = new Package ( path . dirname ( zFindRootPackageJsonPath ( ) ) ) ;
44
31
45
- selectedProjects . split ( "," ) . forEach (
46
- ( p ) => filterProjects . push ( p . trim ( ) )
47
- ) ;
48
- }
32
+ /**
33
+ * Function `addSelectedProjects()` - Function is responsible for extracting selected projects from the command line.
34
+ *
35
+ * It checks if the `--selectedProjects` flag is present in `process.argv`, the array of command-line arguments
36
+ * passed upon the startup of the Node.js process. If the flag is found, it retrieves the subsequent argument
37
+ * which should contain a comma-separated string of project names.
38
+ *
39
+ * In case the argument is missing, it logs a usage message using the `ConsoleManager` and then terminates the
40
+ * process with an exit code of 1.
41
+ *
42
+ * Otherwise, it processes the comma-separated list, trims any whitespace from project names, and
43
+ * appends them to the provided `target` array.
44
+ *
45
+ * It also removes the flag and its associated value from
46
+ * `process.argv`, ensuring they are no longer processed by any other part of the application.
47
+ **/
48
+ function addSelectedProjects ( target : string [ ] ) {
49
+ if ( process . argv . includes ( "--selectedProjects" ) ) {
50
+ const selectedProjectsKey = process . argv . indexOf ( "--selectedProjects" ) ;
51
+ const selectedProjects = process . argv [ selectedProjectsKey + 1 ] ;
52
+
53
+ if ( ! selectedProjects ) {
54
+ ConsoleManager . $ . log ( "Use @z-jest --selectedProjects <project1, project2>" ) ;
55
+ process . exit ( 1 ) ;
56
+ }
49
57
50
- if ( process . argv . includes ( "--runTestsByPath" ) ) {
51
- const runTestsByPathKey = process . argv . indexOf ( "--runTestsByPath" ) ;
52
- const runTestsByPath = process . argv [ runTestsByPathKey + 1 ] ;
58
+ // Remove both key and value
59
+ process . argv . splice ( selectedProjectsKey , 2 ) ;
53
60
54
- if ( ! runTestsByPath ) {
55
- ConsoleManager . $ . log ( "Use @z-jest --runTestsByPath <path>" ) ;
56
- process . exit ( 1 ) ;
61
+ selectedProjects . split ( "," ) . forEach (
62
+ ( p ) => target . push ( p . trim ( ) )
63
+ ) ;
57
64
}
65
+ }
58
66
59
- const packages = zWorkspaceGetPackages ( rootPkg ) ;
67
+ /**
68
+ * Function `addProjectsByPath()` - This method is responsible for retrieving and processing project information
69
+ * based ona specified path.
70
+ *
71
+ * It checks the command-line arguments for the presence of the "--runTestsByPath" flag and, if found,
72
+ * determines the associated path. If the path is specified, it uses the `zWorkspaceGetPackages()` to fetch
73
+ * all workspace packages and finds the one that matches the path.
74
+ *
75
+ * If a matching package is found, its name is added to the target array.
76
+ *
77
+ * If the path argument is missing, it logs a message with usage instructions through `ConsoleManager`
78
+ * and exits the process with a status code of 1, effectively stopping further executions.
79
+ **/
80
+ async function addProjectsByPath ( target : string [ ] ) {
81
+ if ( process . argv . includes ( "--runTestsByPath" ) ) {
82
+ const runTestsByPathKey = process . argv . indexOf ( "--runTestsByPath" ) ;
83
+ const runTestsByPath = process . argv [ runTestsByPathKey + 1 ] ;
84
+
85
+ if ( ! runTestsByPath ) {
86
+ ConsoleManager . $ . log ( "Use @z-jest --runTestsByPath <path>" ) ;
87
+ process . exit ( 1 ) ;
88
+ }
60
89
61
- const matched = Object . values ( packages ) . find ( ( pkg ) => {
62
- return runTestsByPath . includes ( pkg . getPath ( ) ) ;
63
- } ) ;
90
+ const packages = await zWorkspaceGetPackages ( rootPkg ) ;
64
91
65
- if ( matched ) {
66
- filterProjects . push ( matched . json . name ) ;
67
- }
92
+ const matched = Object . values ( packages ) . find ( ( pkg ) => {
93
+ return runTestsByPath . includes ( pkg . getPath ( ) ) ;
94
+ } ) ;
68
95
96
+ if ( matched ) {
97
+ target . push ( matched . json . name ) ;
98
+ }
99
+ }
69
100
}
70
101
71
- async function getProjectsConfig ( ) : Promise < {
72
- pkg : Package ;
73
- config : Config . ProjectConfig | Config . InitialOptions ;
74
- configPath : string ;
75
- normalized ?: Config . ProjectConfig ,
76
- } [ ] > {
102
+ /**
103
+ * Function `getProjectsConfig()` - Retrieve configurations for projects
104
+ * The `getProjectsConfig` function retrieves project configurations by leveraging the `zWorkspaceGetPackages` method,
105
+ * which fetches package information based on the specified root package. After obtaining the packages, the function
106
+ * filters them to include only those matching the provided `filterProjects` criteria and those containing
107
+ * the `jest.config.ts` file.
108
+ *
109
+ * For each filtered package, it dynamically imports the Jest configuration and returns
110
+ * an array of objects containing the package details, configuration, and configuration path.
111
+ **/
112
+ async function getProjectsConfig ( ) : Promise < DZJestProjectConfigInterface [ ] > {
77
113
const packages = await zWorkspaceGetPackages ( rootPkg ) ;
78
114
79
115
return await Promise . all ( Object . values ( packages )
80
116
. filter ( ( pkg ) => {
81
- if ( filterProjects . length > 0 ) {
82
- const match = filterProjects . find ( ( p ) => {
117
+ if ( selectedProjects . length > 0 ) {
118
+ const match = selectedProjects . find ( ( p ) => {
83
119
const regex = new RegExp ( p ) ;
84
120
85
121
return regex . test ( pkg . json . name ) ;
@@ -104,6 +140,87 @@ async function getProjectsConfig(): Promise<{
104
140
} ) ) ;
105
141
}
106
142
143
+ /**
144
+ * Function `updateJestProjectsConfig` - Updates project configurations
145
+ * The method iterates over each project in the `projects` array and modifies their Jest configuration settings.
146
+ *
147
+ * It ensures that each project's configuration has a defined `setupFiles` array by either creating a new empty array
148
+ * if it does not exist or using the existing one.
149
+ *
150
+ * It then prepends a local setup file, located at "setup.js" in the current directory, to this array.
151
+ *
152
+ * In addition, the method sets the `displayName` of the project to the value returned by `getDisplayName()`
153
+ * method of the project's `pkg` object if `displayName` is not already defined.
154
+ *
155
+ * Furthermore, it ensures that the `testRegex` property is set to the `normalized.testRegex` value if `testRegex`
156
+ * is not already present in the project's configuration and returns the updated configuration.
157
+ **/
158
+ function updateJestProjectsConfig ( projects : DZJestProjectConfigInterface [ ] ) : ( Config . ProjectConfig | Config . InitialOptions ) [ ] {
159
+ return projects . map ( ( p => {
160
+ if ( ! p . config . setupFiles ) {
161
+ p . config . setupFiles = [ ] ;
162
+ }
163
+
164
+ // Insert local setup files before the project setup files
165
+ p . config . setupFiles . unshift ( path . join ( currentDirPath , "setup.js" ) ) ;
166
+
167
+ if ( ! p . config . displayName ) {
168
+ p . config . displayName = p . pkg . getDisplayName ( ) ;
169
+ }
170
+
171
+ if ( ! p . config . testRegex && p . normalized ?. testRegex ) {
172
+ p . config . testRegex = p . normalized . testRegex ;
173
+ }
174
+
175
+ return p . config ;
176
+ } ) ) ;
177
+ }
178
+
179
+ /**
180
+ * Function `addCurrentPackageIfAny()` - Function attempts to add the current package to the target
181
+ * list if no other packages are specified in the list.
182
+ *
183
+ * This function first checks if the `target` array is empty.
184
+ *
185
+ * If it is, it proceeds to get all the workspace packages by calling the `zWorkspaceGetPackages` function.
186
+ *
187
+ * Then, it tries to read and parse the current `package.json` file to extract the package's name.
188
+ *
189
+ * If the parsing is successful and the package name exists in the list of workspace packages,
190
+ * it adds this package name to the `target` list.
191
+ *
192
+ * This functionality ensures that when no specific packages are given, the system can utilize the package
193
+ * from the current context if it is part of the workspace.
194
+ **/
195
+ async function addCurrentPackageIfAny ( target : string [ ] ) {
196
+ // If `selectedProjects` is empty, then try lookup running from specific package.
197
+ if ( ! target . length ) {
198
+ // Get all workspaces(packages).
199
+ const workspaces = await zWorkspaceGetPackages ( rootPkg ) ;
200
+
201
+ let packageJSON : { name : string ; } ;
202
+ // Try load current `package.json`
203
+ try {
204
+ packageJSON = JSON . parse ( fs . readFileSync ( process . env [ "npm_package_json" ] , "utf-8" ) ) ;
205
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
206
+ } catch ( e ) {
207
+ // Silence
208
+ }
209
+
210
+ // Check if `packageJSON.name` is in workspaces.
211
+ if ( packageJSON && packageJSON . name && workspaces [ packageJSON . name ] ) {
212
+ target . push ( packageJSON . name ) ;
213
+ }
214
+ }
215
+ }
216
+ const selectedProjects : string [ ] = [ ] ;
217
+
218
+ addSelectedProjects ( selectedProjects ) ;
219
+
220
+ await addProjectsByPath ( selectedProjects ) ;
221
+
222
+ await addCurrentPackageIfAny ( selectedProjects ) ;
223
+
107
224
// Initial config
108
225
const rootConfig : Config . InitialOptions = {
109
226
testRegex : "(/test/.*\\.test\\.(js|cjs))$" ,
@@ -202,25 +319,7 @@ await Promise.all( normalizers ).catch( () => {
202
319
203
320
ConsoleManager . $ . warn = originalWarn ;
204
321
205
- let jestProjects = projects . map ( ( p => {
206
- if ( ! p . config . setupFiles ) {
207
- p . config . setupFiles = [ ] ;
208
- }
209
-
210
- // Insert local setup files before the project setup files
211
- p . config . setupFiles . unshift ( path . join ( __dirname , "setup.js" ) ) ;
212
-
213
- if ( ! p . config . displayName ) {
214
- p . config . displayName = p . pkg . getDisplayName ( ) ;
215
- }
216
-
217
- if ( ! p . config . testRegex && p . normalized . testRegex ) {
218
- p . config . testRegex = p . normalized . testRegex ;
219
- }
220
-
221
- return p . config ;
222
- }
223
- ) ) as any ;
322
+ let jestProjects = updateJestProjectsConfig ( projects ) ;
224
323
225
324
// Hacking jest behavior, since they don't provide "real" flexibility and programmatic usage, but only `runCLI`
226
325
if ( jestProjects . length === 1 ) {
0 commit comments