Skip to content

Commit 0cc696a

Browse files
authored
New: (zenflux-jest) - Add project filtering and configuration enhancements (#89)
Refactor functions for filtering and managing Jest projects. Introduce functions to handle selected projects, projects by path, and current packages. Add definitions export in `package.json` and update TypeScript configuration for better type support.
1 parent 152a8d7 commit 0cc696a

File tree

3 files changed

+164
-64
lines changed

3 files changed

+164
-64
lines changed

packages/zenflux-jest/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/package.json",
32
"name": "@zenflux/jest",
43
"type": "module",
54
"version": "0.1.7",
@@ -13,13 +12,14 @@
1312
"@z-jest": "@z-jest"
1413
},
1514
"exports": {
16-
"./bin/cli.js": "./bin/cli.js"
15+
"./bin/cli.js": "./bin/cli.js",
16+
"./definitions": "./src/definitions.ts"
1717
},
1818
"devDependencies": {
1919
"@zenflux/cli": "workspace:*",
2020
"@zenflux/utils": "workspace:*",
2121
"@jest/globals": "^29.5.5",
22-
"jest": "^29.7.0",
22+
"jest": "29.7.0",
2323
"ts-jest": "^29.1.1",
2424
"ts-node": "^10.9.1"
2525
}

packages/zenflux-jest/src/index.ts

Lines changed: 159 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -18,68 +18,104 @@ import { zWorkspaceGetPackages } from "@zenflux/cli/src/core/workspace";
1818
import { runCLI } from "@jest/core";
1919

2020
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";
2722

2823
if ( process.argv.includes( "--help" ) || process.argv.includes( "-h" ) ) {
2924
ConsoleManager.$.log( "Use jest --help" );
3025
process.exit( 0 );
3126
}
3227

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 ) );
3629

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() ) );
4431

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+
}
4957

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 );
5360

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+
);
5764
}
65+
}
5866

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+
}
6089

61-
const matched = Object.values( packages ).find( ( pkg ) => {
62-
return runTestsByPath.includes( pkg.getPath() );
63-
} );
90+
const packages = await zWorkspaceGetPackages( rootPkg );
6491

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+
} );
6895

96+
if ( matched ) {
97+
target.push( matched.json.name );
98+
}
99+
}
69100
}
70101

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[]> {
77113
const packages = await zWorkspaceGetPackages( rootPkg );
78114

79115
return await Promise.all( Object.values( packages )
80116
.filter( ( pkg ) => {
81-
if ( filterProjects.length > 0 ) {
82-
const match = filterProjects.find( ( p ) => {
117+
if ( selectedProjects.length > 0 ) {
118+
const match = selectedProjects.find( ( p ) => {
83119
const regex = new RegExp( p );
84120

85121
return regex.test( pkg.json.name );
@@ -104,6 +140,87 @@ async function getProjectsConfig(): Promise<{
104140
} ) );
105141
}
106142

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+
107224
// Initial config
108225
const rootConfig: Config.InitialOptions = {
109226
testRegex: "(/test/.*\\.test\\.(js|cjs))$",
@@ -202,25 +319,7 @@ await Promise.all( normalizers ).catch( () => {
202319

203320
ConsoleManager.$.warn = originalWarn;
204321

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 );
224323

225324
// Hacking jest behavior, since they don't provide "real" flexibility and programmatic usage, but only `runCLI`
226325
if ( jestProjects.length === 1 ) {

packages/zenflux-jest/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"baseUrl": "./"
88
},
99
"include": [
10-
"src/*.ts"
10+
"src/*.ts",
11+
"types"
1112
]
1213
}

0 commit comments

Comments
 (0)