or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

config-management.mdindex.mdmulti-project.mdplugin-system.mdpreset-config.mdproject-configuration.mdtest-execution.md

multi-project.mddocs/

0

# Multi-Project Support

1

2

Utilities for working with Jest multi-project configurations in Nx workspaces. This functionality enables running Jest with multiple project configurations simultaneously, supporting complex monorepo testing scenarios.

3

4

## Capabilities

5

6

### Jest Projects Discovery

7

8

Automatically discover and collect Jest project configurations across the workspace.

9

10

```typescript { .api }

11

/**

12

* Get a list of paths to all Jest configuration files using Nx Jest executor

13

* and @nx/run-commands executor running Jest. Used to configure Jest multi-project support.

14

* @returns Promise resolving to array of Jest configuration file paths

15

*/

16

function getJestProjectsAsync(): Promise<string[]>;

17

```

18

19

**Usage Examples:**

20

21

```typescript

22

import { getJestProjectsAsync } from "@nx/jest";

23

24

// Get all Jest project configurations

25

const jestProjects = await getJestProjectsAsync();

26

console.log(jestProjects);

27

// Output: [

28

// '<rootDir>/apps/web-app/jest.config.ts',

29

// '<rootDir>/libs/shared-ui/jest.config.ts',

30

// '<rootDir>/libs/api-client/jest.config.ts'

31

// ]

32

33

// Use in root Jest configuration for multi-project setup

34

export default async () => ({

35

projects: await getJestProjectsAsync()

36

});

37

38

// Add additional custom projects

39

export default async () => ({

40

projects: [

41

...(await getJestProjectsAsync()),

42

'<rootDir>/tools/custom-testing/jest.config.ts'

43

]

44

});

45

```

46

47

### Multi-Project Configuration

48

49

The function integrates with Nx project graph to discover Jest configurations:

50

51

```typescript

52

// Root jest.config.ts example using getJestProjectsAsync

53

import { getJestProjectsAsync } from '@nx/jest';

54

55

export default async () => ({

56

projects: await getJestProjectsAsync(),

57

// Global configuration for all projects

58

coverageReporters: ['html', 'lcov', 'text-summary'],

59

collectCoverageFrom: [

60

'**/*.{js,jsx,ts,tsx}',

61

'!**/*.d.ts',

62

'!**/node_modules/**',

63

],

64

});

65

```

66

67

### Project Detection Logic

68

69

The function discovers Jest projects by analyzing:

70

71

1. **Nx Jest Executor**: Projects using `@nx/jest:jest` or `@nrwl/jest:jest` executor

72

2. **Run Commands Executor**: Projects using `nx:run-commands` executor that run Jest

73

3. **Configuration Files**: Direct analysis of Jest configuration file paths

74

75

**Detection Examples:**

76

77

```json

78

// Detected from project.json with Jest executor

79

{

80

"targets": {

81

"test": {

82

"executor": "@nx/jest:jest",

83

"options": {

84

"jestConfig": "apps/my-app/jest.config.ts"

85

}

86

}

87

}

88

}

89

90

// Detected from run-commands executor

91

{

92

"targets": {

93

"test": {

94

"executor": "nx:run-commands",

95

"options": {

96

"command": "jest --config=apps/my-app/jest.config.ts"

97

}

98

}

99

}

100

}

101

```

102

103

### Path Resolution

104

105

The function returns configuration paths in Jest-compatible format:

106

107

```typescript

108

// Internal path processing

109

function getJestConfigProjectPath(projectJestConfigPath: string): string {

110

return join('<rootDir>', projectJestConfigPath);

111

}

112

113

// Example transformation:

114

// Input: "apps/web-app/jest.config.ts"

115

// Output: "<rootDir>/apps/web-app/jest.config.ts"

116

```

117

118

### Integration with Nx Project Graph

119

120

The function leverages Nx's project graph for efficient project discovery:

121

122

```typescript { .api }

123

interface ProjectGraph {

124

nodes: Record<string, ProjectGraphNode>;

125

dependencies: Record<string, ProjectGraphDependency[]>;

126

}

127

128

interface ProjectGraphNode {

129

name: string;

130

type: string;

131

data: ProjectConfiguration;

132

}

133

```

134

135

**Project Graph Integration:**

136

137

```typescript

138

// Internal implementation pattern

139

export async function getJestProjectsAsync() {

140

const graph = await createProjectGraphAsync({

141

exitOnError: false,

142

resetDaemonClient: true,

143

});

144

145

const jestConfigurations = new Set<string>();

146

147

for (const node of Object.values(graph.nodes)) {

148

const projectConfig = node.data;

149

if (!projectConfig.targets) continue;

150

151

for (const targetConfiguration of Object.values(projectConfig.targets)) {

152

// Process Jest executors and run-commands

153

if (targetConfiguration.executor === '@nx/jest:jest') {

154

collectJestConfigFromJestExecutor(targetConfiguration, jestConfigurations);

155

} else if (targetConfiguration.executor === 'nx:run-commands') {

156

collectJestConfigFromRunCommandsExecutor(

157

targetConfiguration,

158

projectConfig.root,

159

jestConfigurations

160

);

161

}

162

}

163

}

164

165

return Array.from(jestConfigurations);

166

}

167

```

168

169

### Command Parsing for Run Commands

170

171

For `nx:run-commands` executors, the function parses Jest commands to extract configuration paths:

172

173

```typescript

174

// Example run-commands target

175

{

176

"executor": "nx:run-commands",

177

"options": {

178

"command": "jest --config libs/my-lib/jest.config.ts --passWithNoTests"

179

}

180

}

181

182

// Parsed to extract: "libs/my-lib/jest.config.ts"

183

```

184

185

### Common Multi-Project Patterns

186

187

#### Workspace-Wide Testing

188

189

```typescript

190

// jest.config.ts at workspace root

191

import { getJestProjectsAsync } from '@nx/jest';

192

193

export default async () => ({

194

projects: await getJestProjectsAsync(),

195

// Global settings apply to all projects

196

verbose: false,

197

collectCoverageFrom: [

198

'**/*.{js,jsx,ts,tsx}',

199

'!**/*.d.ts',

200

],

201

coverageReporters: ['text-summary', 'html'],

202

coverageDirectory: 'coverage'

203

});

204

```

205

206

#### Selective Project Testing

207

208

```typescript

209

// Filter projects based on specific criteria

210

export default async () => {

211

const allProjects = await getJestProjectsAsync();

212

213

// Only include library projects

214

const libProjects = allProjects.filter(path =>

215

path.includes('/libs/')

216

);

217

218

return {

219

projects: libProjects

220

};

221

};

222

```

223

224

#### Mixed Configuration

225

226

```typescript

227

// Combine auto-discovered projects with manual configurations

228

export default async () => ({

229

projects: [

230

...(await getJestProjectsAsync()),

231

// Add custom test configurations

232

'<rootDir>/tools/integration-tests/jest.config.ts',

233

'<rootDir>/e2e/jest.config.ts'

234

],

235

globalSetup: '<rootDir>/tools/jest-global-setup.ts',

236

globalTeardown: '<rootDir>/tools/jest-global-teardown.ts'

237

});

238

```

239

240

### Performance Considerations

241

242

- **Caching**: Project graph is cached for performance

243

- **Lazy Evaluation**: Projects are discovered only when needed

244

- **Error Handling**: Failed project graph creation doesn't block execution

245

- **Deduplication**: Duplicate configuration paths are automatically removed

246

247

### Migration Support

248

249

The function supports migration from legacy patterns:

250

251

```typescript

252

// Legacy manual project list

253

export default {

254

projects: [

255

'<rootDir>/apps/app1/jest.config.ts',

256

'<rootDir>/apps/app2/jest.config.ts',

257

'<rootDir>/libs/lib1/jest.config.ts'

258

]

259

};

260

261

// Migrated to automatic discovery

262

export default async () => ({

263

projects: await getJestProjectsAsync()

264

});

265

```

266

267

### Error Handling

268

269

The function includes robust error handling:

270

271

- **Graph Creation Errors**: Continues execution with empty project list

272

- **Invalid Configurations**: Skips malformed Jest configurations

273

- **Missing Files**: Handles references to non-existent configuration files

274

- **Permission Errors**: Gracefully handles file system access issues

275

276

### TypeScript Support

277

278

Full TypeScript support with proper type definitions:

279

280

```typescript

281

import type { Config } from 'jest';

282

import { getJestProjectsAsync } from '@nx/jest';

283

284

const config: Config = {

285

projects: await getJestProjectsAsync(),

286

// Additional configuration with full type safety

287

};

288

289

export default config;

290

```