Yeoman Generator Testing Utilities
Yeoman-test provides a comprehensive suite of utilities designed for unit testing Yeoman generators. It simplifies the process of testing generator logic, file system modifications, and user interactions. The current stable version is 11.3.1. Releases occur frequently, often in conjunction with updates to core Yeoman ecosystem packages like `@yeoman/adapter`, `yeoman-environment`, and `yeoman-generator`, ensuring compatibility and leveraging new features. Key differentiators include its tight integration with Yeoman's `mem-fs` virtual file system, enabling robust assertions on generated files and content without touching the actual disk. It facilitates setting up temporary test directories, simulating command-line arguments and user prompts, and asserting file creation, content, and deletion. It also offers mechanisms for mocking composed generators, which is crucial for testing complex generator flows. The library aims to provide a controlled, isolated environment for predictable and reliable generator testing.
Common errors
-
ERR_REQUIRE_ESM: require() of ES Module .../node_modules/yeoman-test/lib/index.js from ... not supported.
cause Attempting to use `require('yeoman-test')` in a CommonJS context when `yeoman-test` v11+ is an ES Module.fixConvert your test files to use ES Module `import` syntax (`import helpers from 'yeoman-test';`). Ensure your project or test files are configured for ESM (e.g., `"type": "module"` in `package.json` or `.mjs` file extensions). -
TypeError: Cannot read properties of undefined (reading 'assertFile')
cause The `result` object or its methods are accessed before a generator has been successfully run, or `result` was not properly imported.fixEnsure that `await helpers.run(...)` has completed before attempting to use `result` for assertions. Verify `import { result } from 'yeoman-test';` is present and correctly scoped. -
Error: You don't have yeoman-environment installed. Try npm install yeoman-environment.
cause Missing `yeoman-environment` peer dependency or an incompatible version installed, preventing `yeoman-test` from initializing the generator environment.fixInstall or upgrade `yeoman-environment` to a compatible version as specified in `yeoman-test`'s `peerDependencies`. For `yeoman-test@11`, this typically means `yeoman-environment@^4.0.0 || ^5.0.0-beta.0 || ^6.0.0`.
Warnings
- breaking Version 11.0.0 of `yeoman-test` raises the minimum required Node.js version to `^20.6.1 || >=22`. Projects running on older Node.js versions will need to upgrade their Node.js environment or remain on `yeoman-test` v10.x. This change also implies an shift towards ESM-first module resolution.
- breaking `yeoman-test` is tightly coupled with `yeoman-environment` and `yeoman-generator`. Major version bumps in `yeoman-test` (e.g., v11) often coincide with breaking changes or new peer dependency requirements for these core Yeoman packages. Incompatible versions can lead to runtime errors or unexpected behavior.
- gotcha With the shift to modern Node.js versions (v20+) and the project's move towards ESM, using CommonJS `require()` statements for `yeoman-test` might lead to `ERR_REQUIRE_ESM` errors, especially when integrating with test runners that default to CommonJS.
- gotcha The `result` object, imported as a named export, holds the `RunResult` instance of the *last* executed `helpers.run()` command. If you perform multiple `helpers.run()` or `result.create().run()` calls within the same test block or `beforeEach`, `result` will only reflect the final one, potentially leading to incorrect assertions if you expect an earlier run's state.
Install
-
npm install yeoman-test -
yarn add yeoman-test -
pnpm add yeoman-test
Imports
- helpers
const helpers = require('yeoman-test');import helpers, { result } from 'yeoman-test'; - run
import { run } from 'yeoman-test';import helpers from 'yeoman-test'; await helpers.run('namespace'); - RunResult (type)
import { type RunResult } from 'yeoman-test';
Quickstart
import helpers, { result } from 'yeoman-test';
import assert from 'assert';
describe('generator test suite', () => {
// Define a dummy generator namespace or point to a local generator path
const generatorNamespace = 'my-generator:app';
beforeEach(async () => {
// Ensure your generator and its dependencies are installed:
// npm install --save-dev yeoman-generator yeoman-environment
// npm install --save-dev yeoman-test
// This will run the generator in a temporary directory
await helpers
.run(generatorNamespace)
.withOptions({ skipInstall: true, someOption: 'value' })
.withPrompts({ name: 'my-project', features: ['featureA'] });
});
it('creates a project directory and a specific file', () => {
// Assertions using the global result object from the last run
result.assertNoFileContent('package.json', /"private": true/);
result.assertFile('my-project/package.json');
result.assertFileContent('my-project/package.json', /"name": "my-project"/);
result.assertJsonFileContent('my-project/package.json', { dependencies: { lodash: '^4.0.0' } });
});
it('can create additional generators in the same context', async () => {
// Use result.create to run another generator within the same temporary directory
await result.create('another-generator:sub').run();
result.assertFile('my-project/src/sub-feature.js');
});
it('handles composed generators correctly', async () => {
// Mock a composed generator to verify interaction without running its full logic
await helpers.run('my-generator:app').withMockedGenerators(['composed:feature']);
assert(result.mockedGenerators['composed:feature'].calledOnce);
});
});