or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

generator-helpers.mdindex.mdrun-context.mdrun-result.mdtest-adapter.mdtest-environment.md

run-context.mddocs/

0

# Test Execution Context

1

2

The RunContext provides a fluent, chainable API for configuring and executing generator tests. It manages the complete test lifecycle from setup through execution to cleanup, with support for temporary directories, file system mocking, prompt simulation, and generator composition.

3

4

## Context Properties

5

6

The RunContext exposes several properties for advanced test scenarios:

7

8

```typescript { .api }

9

interface RunContext<GeneratorType> {

10

/** The generator instance being tested */

11

generator: GeneratorType;

12

13

/** The Yeoman environment instance */

14

env: DefaultEnvironmentApi;

15

16

/** Memory file system store */

17

memFs: Store<MemFsEditorFile>;

18

19

/** Memory file system editor */

20

editor: MemFsEditor;

21

22

/** Context configuration settings */

23

settings: RunContextSettings;

24

25

/** Environment options */

26

envOptions: BaseEnvironmentOptions;

27

28

/** Whether the test has completed */

29

completed: boolean;

30

31

/** Target directory for the test */

32

targetDirectory?: string;

33

34

/** Mocked generators for composition testing */

35

mockedGenerators: Record<string, BaseGenerator>;

36

37

/** Mock spawn stub when using spawn mocking */

38

spawnStub?: any;

39

40

/** Questions asked during prompt simulation */

41

askedQuestions: AskedQuestions;

42

}

43

```

44

45

## Capabilities

46

47

### Creating Run Contexts

48

49

Create and configure test execution contexts for generator testing.

50

51

```typescript { .api }

52

/**

53

* Run the provided Generator in a test context

54

* @param GeneratorOrNamespace - Generator constructor or namespace

55

* @param settings - Configuration options for the run context

56

* @param environmentOptions - Options for the Yeoman environment

57

* @returns RunContext instance for chaining configuration

58

*/

59

function run<GeneratorType extends BaseGenerator = DefaultGeneratorApi>(

60

GeneratorOrNamespace: string | GetGeneratorConstructor<GeneratorType>,

61

settings?: RunContextSettings,

62

environmentOptions?: BaseEnvironmentOptions

63

): RunContext<GeneratorType>;

64

65

/**

66

* Alias for run() - prepare a run context

67

* @param GeneratorOrNamespace - Generator constructor or namespace

68

* @param settings - Configuration options

69

* @param environmentOptions - Environment options

70

* @returns RunContext instance

71

*/

72

function create<GeneratorType extends BaseGenerator = DefaultGeneratorApi>(

73

GeneratorOrNamespace: string | GetGeneratorConstructor<GeneratorType>,

74

settings?: RunContextSettings,

75

environmentOptions?: BaseEnvironmentOptions

76

): RunContext<GeneratorType>;

77

78

/**

79

* Prepare temporary dir without generator support

80

* @param settings - Configuration options

81

* @returns BasicRunContext for directory-only testing

82

*/

83

function prepareTemporaryDir(settings?: RunContextSettings): BasicRunContext;

84

```

85

86

**Usage Examples:**

87

88

```typescript

89

import helpers from "yeoman-test";

90

91

// Basic generator test

92

const context = helpers.run("my-generator");

93

94

// Generator from file path

95

const context = helpers.run("./path/to/generator");

96

97

// With custom settings

98

const context = helpers.run("my-generator", {

99

tmpdir: false,

100

cwd: "/custom/path"

101

});

102

103

// Directory-only testing

104

const context = helpers.prepareTemporaryDir();

105

```

106

107

### Configuration Methods

108

109

Configure generator arguments, options, and behavior before execution.

110

111

```typescript { .api }

112

/**

113

* Provide arguments to the run context

114

* @param args - Command line arguments as Array or space separated string

115

* @returns this for method chaining

116

*/

117

withArguments(args: string | string[]): this;

118

119

/**

120

* Provide options to the run context

121

* @param options - Command line options (e.g. --opt-one=foo)

122

* @returns this for method chaining

123

*/

124

withOptions(options: Partial<Omit<GetGeneratorOptions<GeneratorType>, 'env' | 'namespace' | 'resolved'>>): this;

125

126

/**

127

* Mock answers for prompts

128

* @param answers - Answers to the prompt questions

129

* @param options - Additional prompt options

130

* @returns this for method chaining

131

*/

132

withAnswers(answers: PromptAnswers, options?: Omit<DummyPromptOptions, 'mockedAnswers'>): this;

133

134

/**

135

* @deprecated Use withAnswers instead

136

* Mock the prompt with dummy answers

137

*/

138

withPrompts(answers: PromptAnswers, options?: Omit<DummyPromptOptions, 'mockedAnswers'>): this;

139

```

140

141

**Usage Examples:**

142

143

```typescript

144

await helpers.run("my-generator")

145

.withArguments(["arg1", "arg2"])

146

.withOptions({

147

skipInstall: true,

148

force: true

149

})

150

.withAnswers({

151

projectName: "test-app",

152

features: ["typescript", "testing"]

153

});

154

155

// Arguments as string

156

await helpers.run("my-generator")

157

.withArguments("init --force");

158

```

159

160

### File System Setup

161

162

Configure files, directories, and configuration before generator execution.

163

164

```typescript { .api }

165

/**

166

* Add files to mem-fs. Files will be resolved relative to targetDir.

167

* Files with Object content will be merged to existing content.

168

* @param files - Object mapping file paths to content

169

* @returns this for method chaining

170

*/

171

withFiles(files: Record<string, string | Record<string, unknown>>): this;

172

173

/**

174

* Add files to specific relative path

175

* @param relativePath - Path relative to target directory

176

* @param files - Object mapping file paths to content

177

* @returns this for method chaining

178

*/

179

withFiles(relativePath: string, files: Record<string, string | Record<string, unknown>>): this;

180

181

/**

182

* Add .yo-rc.json to mem-fs

183

* @param content - Content for .yo-rc.json as string or object

184

* @returns this for method chaining

185

*/

186

withYoRc(content: string | Record<string, unknown>): this;

187

188

/**

189

* Add a generator config to .yo-rc.json

190

* @param key - Generator key for the configuration

191

* @param content - Configuration object

192

* @returns this for method chaining

193

*/

194

withYoRcConfig(key: string, content: Record<string, unknown>): this;

195

196

/**

197

* Mock the local configuration with the provided config

198

* @param localConfig - Should look like config.getAll() output

199

* @returns this for method chaining

200

*/

201

withLocalConfig(localConfig: any): this;

202

203

/**

204

* Commit mem-fs files to disk

205

* @returns this for method chaining

206

*/

207

commitFiles(): this;

208

```

209

210

**Usage Examples:**

211

212

```typescript

213

await helpers.run("my-generator")

214

.withFiles({

215

"package.json": '{"name": "existing-project"}',

216

"config.json": { theme: "dark", debug: true },

217

"templates/base.hbs": "Hello {{name}}"

218

})

219

.withYoRcConfig("my-generator", {

220

previousRun: true,

221

settings: { typescript: true }

222

})

223

.commitFiles();

224

225

// Files in subdirectory

226

await helpers.run("my-generator")

227

.withFiles("src", {

228

"index.ts": "export * from './lib';",

229

"lib.ts": "export const VERSION = '1.0.0';"

230

});

231

```

232

233

### Generator Dependencies

234

235

Configure dependent generators and mocked generators for composition testing.

236

237

```typescript { .api }

238

/**

239

* Provide dependent generators

240

* @param dependencies - Paths to generators or [generator, options] pairs

241

* @returns this for method chaining

242

*/

243

withGenerators(dependencies: Dependency[]): this;

244

245

/**

246

* Create mocked generators for testing composition

247

* @param namespaces - Namespaces of mocked generators

248

* @returns this for method chaining

249

*/

250

withMockedGenerators(namespaces: string[]): this;

251

252

/**

253

* Provide custom mocked generator factory

254

* @param mockedGeneratorFactory - Factory function for creating mocked generators

255

* @returns this for method chaining

256

*/

257

withMockedGeneratorFactory(mockedGeneratorFactory: MockedGeneratorFactory): this;

258

259

type Dependency = string | Parameters<DefaultEnvironmentApi['register']>;

260

type MockedGeneratorFactory<GenParameter extends BaseGenerator = DefaultGeneratorApi> = (

261

GeneratorClass?: GetGeneratorConstructor<GenParameter>

262

) => GetGeneratorConstructor<GenParameter>;

263

```

264

265

**Usage Examples:**

266

267

```typescript

268

await helpers.run("my-generator")

269

.withGenerators([

270

"./path/to/dep-generator",

271

["./other-generator", { namespace: "custom:name" }]

272

])

273

.withMockedGenerators([

274

"sub-generator:app",

275

"common:util"

276

]);

277

278

// Access mocked generators in tests

279

it("composes with sub-generator", () => {

280

result.assertGeneratorComposed("sub-generator:app");

281

const mock = result.getGeneratorMock("sub-generator:app");

282

expect(mock.callCount()).toBe(1);

283

});

284

```

285

286

### Environment Configuration

287

288

Configure the Yeoman environment and lookup behavior.

289

290

```typescript { .api }

291

/**

292

* Run lookup on the environment

293

* @param lookups - Lookup options to run

294

* @returns this for method chaining

295

*/

296

withLookups(lookups: LookupOptions | LookupOptions[]): this;

297

298

/**

299

* Customize environment creation

300

* @param callback - Callback to modify environment

301

* @returns this for method chaining

302

*/

303

withEnvironment(callback: (env: DefaultEnvironmentApi) => any): this;

304

305

/**

306

* Customize environment run method

307

* @param callback - Custom run implementation

308

* @returns this for method chaining

309

*/

310

withEnvironmentRun(callback: (this: this, env: DefaultEnvironmentApi, gen: GeneratorType) => void): this;

311

312

/**

313

* TestAdapter options for prompt mocking

314

* @param options - Adapter configuration options

315

* @returns this for method chaining

316

*/

317

withAdapterOptions(options: Omit<TestAdapterOptions, 'mockedAnswers'>): this;

318

```

319

320

### Spawn Command Mocking

321

322

Mock spawn calls for testing generators that execute external commands.

323

324

```typescript { .api }

325

/**

326

* Mock spawn calls with custom stub or default implementation

327

* @param options - Stub function or configuration object

328

* @returns this for method chaining

329

*/

330

withSpawnMock<StubType = ReturnType<typeof mock.fn>>(

331

options?: ((...args) => any) | {

332

stub?: (...args) => any;

333

registerNodeMockDefaults?: boolean;

334

callback?: ({ stub, implementation }: { stub: StubType; implementation: any }) => void | Promise<void>;

335

}

336

): this;

337

```

338

339

**Usage Examples:**

340

341

```typescript

342

// Default spawn mocking

343

await helpers.run("my-generator")

344

.withSpawnMock();

345

346

// Custom spawn behavior

347

await helpers.run("my-generator")

348

.withSpawnMock({

349

stub: mock.fn(() => ({ exitCode: 0, stdout: "success" })),

350

callback: ({ stub }) => {

351

// Configure stub behavior

352

stub.mockReturnValueOnce({ exitCode: 1, stderr: "error" });

353

}

354

});

355

356

// Access spawn calls in tests

357

it("runs expected commands", () => {

358

const spawnArgs = result.getSpawnArgsUsingDefaultImplementation();

359

expect(spawnArgs[0]).toEqual(["spawnCommand", "npm", ["install"]]);

360

});

361

```

362

363

### Directory Management

364

365

Configure working directories and temporary directory behavior.

366

367

```typescript { .api }

368

/**

369

* @deprecated Clean the provided directory, then change directory into it

370

* @param dirPath - Directory path (relative to CWD)

371

* @param callback - Callback receiving the folder path

372

* @returns this for method chaining

373

*/

374

inDir(dirPath: string, callback?: (folderPath: string) => void): this;

375

376

/**

377

* @deprecated Change directory without deleting directory content

378

* @param dirPath - Directory path (relative to CWD)

379

* @returns this for method chaining

380

*/

381

cd(dirPath: string): this;

382

383

/**

384

* Cleanup a temporary directory and change the CWD into it

385

* @param callback - Callback receiving the folder path

386

* @returns this for method chaining

387

*/

388

inTmpDir(callback?: (folderPath: string) => void): this;

389

390

/**

391

* Register a callback to prepare the destination folder

392

* @param callback - Callback receiving the folder path

393

* @returns this for method chaining

394

*/

395

doInDir(callback: (folderPath: string) => void): this;

396

```

397

398

### Lifecycle Callbacks

399

400

Configure callbacks for different stages of the test execution.

401

402

```typescript { .api }

403

/**

404

* Execute callback when generator is ready

405

* @param callback - Callback receiving the generator instance

406

* @returns this for method chaining

407

*/

408

onGenerator(callback: (this: this, generator: GeneratorType) => any): this;

409

410

/**

411

* Execute callback when environment is ready

412

* @param callback - Callback receiving the environment instance

413

* @returns this for method chaining

414

*/

415

onEnvironment(callback: (this: this, environment: DefaultEnvironmentApi) => any): this;

416

417

/**

418

* Execute callback when target directory is set

419

* @param callback - Callback receiving the target directory path

420

* @returns this for method chaining

421

*/

422

onTargetDirectory(callback: (this: this, targetDirectory: string) => any): this;

423

424

/**

425

* Execute callback before preparation phase

426

* @param callback - Callback executed before test preparation

427

* @returns this for method chaining

428

*/

429

onBeforePrepare(callback: (this: this) => void | Promise<void>): this;

430

```

431

432

**Usage Examples:**

433

434

```typescript

435

await helpers.run("my-generator")

436

.onGenerator(generator => {

437

// Customize generator before execution

438

generator.options.customFlag = true;

439

})

440

.onEnvironment(env => {

441

// Configure environment

442

env.register("./custom-generator", { namespace: "custom:gen" });

443

})

444

.onTargetDirectory(targetDir => {

445

// Setup target directory

446

fs.writeFileSync(path.join(targetDir, "preset.json"), "{}");

447

});

448

```

449

450

### Execution and State Management

451

452

Execute the generator and manage test state.

453

454

```typescript { .api }

455

/**

456

* Run the generator and return results

457

* @returns Promise resolving to RunResult instance

458

*/

459

run(): Promise<RunResult<GeneratorType>>;

460

461

/**

462

* Build/prepare the context without running the generator

463

* @returns Promise resolving when context is ready

464

*/

465

build(): Promise<void>;

466

467

/**

468

* Prepare the test context without running

469

* @returns Promise resolving when preparation is complete

470

*/

471

prepare(): Promise<void>;

472

473

/**

474

* Don't reset mem-fs state to aggregate snapshots from multiple runs

475

* @returns this for method chaining

476

*/

477

withKeepFsState(): this;

478

479

/**

480

* Clean the directory used for tests and restore original working directory

481

*/

482

cleanup(): void;

483

484

/**

485

* Clean the temporary directory

486

*/

487

cleanupTemporaryDir(): void;

488

489

/**

490

* Clean the test directory with optional force flag

491

* @param force - Force cleanup even if directory is not temporary

492

* @returns this for method chaining

493

*/

494

cleanTestDirectory(force?: boolean): this;

495

496

/**

497

* Restore original working directory

498

* @returns this for method chaining

499

*/

500

restore(): this;

501

```

502

503

## RunContext Promise Interface

504

505

RunContext implements the Promise interface for convenient async/await usage:

506

507

```typescript { .api }

508

/**

509

* RunContext implements Promise<RunResult<GeneratorType>>

510

*/

511

interface RunContext<GeneratorType> extends Promise<RunResult<GeneratorType>> {

512

then<TResult1, TResult2>(

513

onfulfilled?: (value: RunResult<GeneratorType>) => TResult1 | PromiseLike<TResult1>,

514

onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>

515

): Promise<TResult1 | TResult2>;

516

517

catch<TResult>(

518

onrejected?: (reason: any) => TResult | PromiseLike<TResult>

519

): Promise<RunResult<GeneratorType> | TResult>;

520

521

finally(onfinally?: () => void): Promise<RunResult<GeneratorType>>;

522

}

523

```

524

525

**Usage Examples:**

526

527

```typescript

528

// Promise-style usage

529

const result = await helpers.run("my-generator")

530

.withOptions({ skipInstall: true });

531

532

// Traditional promise chains

533

helpers.run("my-generator")

534

.then(result => {

535

result.assertFile("package.json");

536

})

537

.catch(error => {

538

console.error("Test failed:", error);

539

});

540

```