yeoman-test 7.2.0 → 7.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -2
- package/dist/helpers.d.ts +10 -6
- package/dist/helpers.js +16 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run-context.d.ts +27 -6
- package/dist/run-context.js +83 -35
- package/dist/run-result.d.ts +1 -1
- package/dist/run-result.js +2 -1
- package/dist/test-context.d.ts +8 -2
- package/dist/test-context.js +16 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ $ npm install --save-dev yeoman-generator@xxx yeoman-environment@xxx
|
|
|
25
25
|
Usage:
|
|
26
26
|
|
|
27
27
|
```js
|
|
28
|
+
import helpers from 'yeoman-test';
|
|
29
|
+
|
|
28
30
|
describe('generator test', () => {
|
|
29
31
|
describe('test', () => {
|
|
30
32
|
let runResult;
|
|
@@ -36,12 +38,22 @@ describe('generator test', () => {
|
|
|
36
38
|
{} // environment options
|
|
37
39
|
)
|
|
38
40
|
[.cd(dir)] // runs the test inside a non temporary dir
|
|
39
|
-
[.
|
|
41
|
+
[.onTargetDirectory(dir => {}) // prepares the test dir
|
|
40
42
|
[.withGenerators([])] // registers additional generators
|
|
41
43
|
[.withLookups({})] // runs Environment lookups
|
|
42
44
|
[.withOptions({})] // passes options to the generator
|
|
43
45
|
[.withLocalConfig({})] // sets the generator config as soon as it is instantiated
|
|
44
|
-
[.
|
|
46
|
+
[.withAnswers()] // simulates the prompt answers
|
|
47
|
+
[.withMockedGenerators(['namespace', ...])] // adds a mocked generator to the namespaces
|
|
48
|
+
[.withFiles({
|
|
49
|
+
'foo.txt': 'bar',
|
|
50
|
+
'test.json', { content: true },
|
|
51
|
+
})] // add files to mem-fs
|
|
52
|
+
[.withYoRc({ 'generator-foo': { bar: {} } })] // add config to .yo-rc.json
|
|
53
|
+
[.withYoRcConfig('generator-foo.bar', { : {} })] // same as above
|
|
54
|
+
[.commitFiles()] // commit mem-fs files to disk
|
|
55
|
+
[.onGenerator(gen => {})] // do something with the generator
|
|
56
|
+
[.onEnvironment(env => {})] // do something with the environment
|
|
45
57
|
[.build(runContext => { // instantiates Environment/Generator
|
|
46
58
|
[runContext.env...] // does something with the environment
|
|
47
59
|
[runContext.generator...] // does something with the generator
|
|
@@ -51,6 +63,7 @@ describe('generator test', () => {
|
|
|
51
63
|
);
|
|
52
64
|
afterEach(() => {
|
|
53
65
|
if (runResult) {
|
|
66
|
+
// Optional if context is executed at a temporary folder
|
|
54
67
|
runResult.restore();
|
|
55
68
|
}
|
|
56
69
|
});
|
|
@@ -68,6 +81,46 @@ describe('generator test', () => {
|
|
|
68
81
|
});
|
|
69
82
|
```
|
|
70
83
|
|
|
84
|
+
Convenience last RunResult instance:
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
import helpers, { result } from 'yeoman-test';
|
|
88
|
+
|
|
89
|
+
describe('generator test', () => {
|
|
90
|
+
before(() => helpers.run('namespace'));
|
|
91
|
+
it('test', () => {
|
|
92
|
+
result.assert...;
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Generator compose:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
import assert from 'assert';
|
|
101
|
+
import helpers, { result } from 'yeoman-test';
|
|
102
|
+
|
|
103
|
+
describe('my-gen', () => {
|
|
104
|
+
before(() => helpers.run('my-gen').withMockedGenerator(['composed-gen']));
|
|
105
|
+
it('should compose with composed-gen', () => {
|
|
106
|
+
assert(result.mockedGenerators['composed-gen'].calledOnce);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Generic test folder:
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
import helpers, { result } from 'yeoman-test';
|
|
115
|
+
|
|
116
|
+
describe('generic test', () => {
|
|
117
|
+
before(() => helpers.prepareTemporaryDir());
|
|
118
|
+
it('test', () => {
|
|
119
|
+
result.assert...;
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
71
124
|
[See our api documentation](https://yeoman.github.io/yeoman-test) for latest yeoman-test release.
|
|
72
125
|
|
|
73
126
|
[See our api documentation](https://yeoman.github.io/yeoman-test/5.0.1) for yeoman-test 5.0.1. Use 5.x for yeoman-environment 2.x support.
|
package/dist/helpers.d.ts
CHANGED
|
@@ -4,14 +4,13 @@ import type { GeneratorOptions } from 'yeoman-generator';
|
|
|
4
4
|
import type { Options, createEnv } from 'yeoman-environment';
|
|
5
5
|
import type { SinonSpiedInstance } from 'sinon';
|
|
6
6
|
import { type DummyPromptOptions } from './adapter.js';
|
|
7
|
-
import RunContext from './run-context.js';
|
|
8
|
-
import type { RunContextSettings } from './run-context.js';
|
|
7
|
+
import RunContext, { BasicRunContext, type RunContextSettings } from './run-context.js';
|
|
9
8
|
/**
|
|
10
9
|
* Dependencies can be path (autodiscovery) or an array [<generator>, <name>]
|
|
11
10
|
*/
|
|
12
11
|
export type Dependency = string | Parameters<Environment['registerStub']> | Parameters<Environment['register']>;
|
|
13
|
-
type GeneratorNew<GenParameter extends YeomanGenerator = YeomanGenerator> = new (...args: ConstructorParameters<typeof YeomanGenerator<GenParameter['options']>>) =>
|
|
14
|
-
type GeneratorBuilder<GenParameter extends YeomanGenerator = YeomanGenerator> = (...args: ConstructorParameters<typeof YeomanGenerator<GenParameter['options']>>) =>
|
|
12
|
+
type GeneratorNew<GenParameter extends YeomanGenerator = YeomanGenerator> = new (...args: ConstructorParameters<typeof YeomanGenerator<GenParameter['options']>>) => GenParameter;
|
|
13
|
+
type GeneratorBuilder<GenParameter extends YeomanGenerator = YeomanGenerator> = (...args: ConstructorParameters<typeof YeomanGenerator<GenParameter['options']>>) => GenParameter;
|
|
15
14
|
export type GeneratorConstructor<GenParameter extends YeomanGenerator = YeomanGenerator> = GeneratorNew<GenParameter> | GeneratorBuilder<GenParameter>;
|
|
16
15
|
/**
|
|
17
16
|
* Collection of unit test helpers. (mostly related to Mocha syntax)
|
|
@@ -137,13 +136,18 @@ export declare class YeomanTest {
|
|
|
137
136
|
* Run the provided Generator
|
|
138
137
|
* @param GeneratorOrNamespace - Generator constructor or namespace
|
|
139
138
|
*/
|
|
140
|
-
run<GeneratorType extends YeomanGenerator = YeomanGenerator>(GeneratorOrNamespace: string | GeneratorConstructor
|
|
139
|
+
run<GeneratorType extends YeomanGenerator = YeomanGenerator>(GeneratorOrNamespace: string | GeneratorConstructor<GeneratorType>, settings?: RunContextSettings, envOptions?: Options): RunContext<GeneratorType>;
|
|
141
140
|
/**
|
|
142
141
|
* Prepare a run context
|
|
143
142
|
* @param {String|Function} GeneratorOrNamespace - Generator constructor or namespace
|
|
144
143
|
* @return {RunContext}
|
|
145
144
|
*/
|
|
146
|
-
create<GeneratorType extends YeomanGenerator = YeomanGenerator>(GeneratorOrNamespace: string | GeneratorConstructor
|
|
145
|
+
create<GeneratorType extends YeomanGenerator = YeomanGenerator>(GeneratorOrNamespace: string | GeneratorConstructor<GeneratorType>, settings?: RunContextSettings, envOptions?: Options): RunContext<GeneratorType>;
|
|
146
|
+
/**
|
|
147
|
+
* Prepare temporary dir without generator support.
|
|
148
|
+
* Generator and environment will be undefined.
|
|
149
|
+
*/
|
|
150
|
+
prepareTemporaryDir(settings?: RunContextSettings): BasicRunContext;
|
|
147
151
|
}
|
|
148
152
|
declare const _default: YeomanTest;
|
|
149
153
|
export default _default;
|
package/dist/helpers.js
CHANGED
|
@@ -7,8 +7,9 @@ import { spy as sinonSpy, stub as sinonStub } from 'sinon';
|
|
|
7
7
|
import YeomanGenerator from 'yeoman-generator';
|
|
8
8
|
import Environment from 'yeoman-environment';
|
|
9
9
|
import { DummyPrompt, TestAdapter } from './adapter.js';
|
|
10
|
-
import RunContext from './run-context.js';
|
|
10
|
+
import RunContext, { BasicRunContext } from './run-context.js';
|
|
11
11
|
import testContext from './test-context.js';
|
|
12
|
+
const { cloneDeep } = _;
|
|
12
13
|
/**
|
|
13
14
|
* Collection of unit test helpers. (mostly related to Mocha syntax)
|
|
14
15
|
* @class YeomanTest
|
|
@@ -206,7 +207,7 @@ export class YeomanTest {
|
|
|
206
207
|
* const env = createTestEnv(require('yeoman-environment').createEnv);
|
|
207
208
|
*/
|
|
208
209
|
createTestEnv(envContructor = this.createEnv, options = { localConfigOnly: true }) {
|
|
209
|
-
const envOptions =
|
|
210
|
+
const envOptions = cloneDeep(this.environmentOptions ?? {});
|
|
210
211
|
if (typeof options === 'boolean') {
|
|
211
212
|
options = {
|
|
212
213
|
newErrorHandler: true,
|
|
@@ -243,8 +244,8 @@ export class YeomanTest {
|
|
|
243
244
|
* @param GeneratorOrNamespace - Generator constructor or namespace
|
|
244
245
|
*/
|
|
245
246
|
run(GeneratorOrNamespace, settings, envOptions) {
|
|
246
|
-
const contextSettings =
|
|
247
|
-
const generatorOptions =
|
|
247
|
+
const contextSettings = cloneDeep(this.settings ?? {});
|
|
248
|
+
const generatorOptions = cloneDeep(this.generatorOptions ?? {});
|
|
248
249
|
const RunContext = this.getRunContextType();
|
|
249
250
|
const runContext = new RunContext(GeneratorOrNamespace, { ...contextSettings, ...settings }, envOptions, this).withOptions(generatorOptions);
|
|
250
251
|
if (settings?.autoCleanup !== false) {
|
|
@@ -260,6 +261,17 @@ export class YeomanTest {
|
|
|
260
261
|
create(GeneratorOrNamespace, settings, envOptions) {
|
|
261
262
|
return this.run(GeneratorOrNamespace, settings, envOptions);
|
|
262
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Prepare temporary dir without generator support.
|
|
266
|
+
* Generator and environment will be undefined.
|
|
267
|
+
*/
|
|
268
|
+
prepareTemporaryDir(settings) {
|
|
269
|
+
const context = new BasicRunContext(undefined, settings);
|
|
270
|
+
if (settings?.autoCleanup !== false) {
|
|
271
|
+
testContext.startNewContext(context);
|
|
272
|
+
}
|
|
273
|
+
return context;
|
|
274
|
+
}
|
|
263
275
|
}
|
|
264
276
|
export default new YeomanTest();
|
|
265
277
|
export const createHelpers = options => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default, createHelpers, YeomanTest, type Dependency } from './helpers.js';
|
|
2
2
|
export { default as RunContext, RunContextBase, type RunContextSettings } from './run-context.js';
|
|
3
3
|
export { default as RunResult, type RunResultOptions } from './run-result.js';
|
|
4
|
-
export { default as context } from './test-context.js';
|
|
4
|
+
export { default as context, result } from './test-context.js';
|
|
5
5
|
export { DummyPrompt, TestAdapter } from './adapter.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default, createHelpers, YeomanTest } from './helpers.js';
|
|
2
2
|
export { default as RunContext, RunContextBase } from './run-context.js';
|
|
3
3
|
export { default as RunResult } from './run-result.js';
|
|
4
|
-
export { default as context } from './test-context.js';
|
|
4
|
+
export { default as context, result } from './test-context.js';
|
|
5
5
|
export { DummyPrompt, TestAdapter } from './adapter.js';
|
package/dist/run-context.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import type Generator from 'yeoman-generator';
|
|
|
4
4
|
import type Environment from 'yeoman-environment';
|
|
5
5
|
import { type LookupOptions, type Options } from 'yeoman-environment';
|
|
6
6
|
import MemFsEditor from 'mem-fs-editor';
|
|
7
|
-
import
|
|
7
|
+
import MemFs from 'mem-fs';
|
|
8
|
+
import RunResult, { type RunResultOptions } from './run-result.js';
|
|
8
9
|
import { type GeneratorConstructor, type Dependency, type YeomanTest } from './helpers.js';
|
|
9
10
|
import { type DummyPromptOptions } from './adapter.js';
|
|
10
11
|
/**
|
|
@@ -20,6 +21,7 @@ export type RunContextSettings = {
|
|
|
20
21
|
oldCwd?: string;
|
|
21
22
|
forwardCwd?: boolean;
|
|
22
23
|
autoCleanup?: boolean;
|
|
24
|
+
memFs?: MemFs.Store;
|
|
23
25
|
/**
|
|
24
26
|
* File path to the generator (only used if Generator is a constructor)
|
|
25
27
|
*/
|
|
@@ -31,6 +33,7 @@ export type RunContextSettings = {
|
|
|
31
33
|
namespace?: string;
|
|
32
34
|
};
|
|
33
35
|
type PromiseRunResult<GeneratorType extends Generator> = Promise<RunResult<GeneratorType>>;
|
|
36
|
+
type MockedGeneratorFactory = (GeneratorClass?: typeof Generator) => typeof Generator;
|
|
34
37
|
export declare class RunContextBase<GeneratorType extends Generator = Generator> extends EventEmitter {
|
|
35
38
|
readonly mockedGenerators: Record<string, Generator>;
|
|
36
39
|
env: Environment;
|
|
@@ -40,15 +43,18 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
40
43
|
completed: boolean;
|
|
41
44
|
targetDirectory?: string;
|
|
42
45
|
editor: MemFsEditor.Editor;
|
|
46
|
+
memFs: MemFs.Store;
|
|
47
|
+
mockedGeneratorFactory: MockedGeneratorFactory;
|
|
43
48
|
protected environmentPromise?: PromiseRunResult<GeneratorType>;
|
|
44
49
|
private args;
|
|
45
50
|
private options;
|
|
46
51
|
private answers?;
|
|
52
|
+
private keepFsState?;
|
|
47
53
|
private readonly onGeneratorCallbacks;
|
|
48
54
|
private readonly onTargetDirectoryCallbacks;
|
|
49
55
|
private readonly onEnvironmentCallbacks;
|
|
50
56
|
private readonly inDirCallbacks;
|
|
51
|
-
private readonly Generator
|
|
57
|
+
private readonly Generator?;
|
|
52
58
|
private readonly helpers;
|
|
53
59
|
private readonly temporaryDir;
|
|
54
60
|
private oldCwd?;
|
|
@@ -67,7 +73,7 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
67
73
|
* @param settings
|
|
68
74
|
* @return {this}
|
|
69
75
|
*/
|
|
70
|
-
constructor(generatorType
|
|
76
|
+
constructor(generatorType?: string | GeneratorConstructor<GeneratorType> | typeof Generator, settings?: RunContextSettings, envOptions?: Options, helpers?: YeomanTest);
|
|
71
77
|
/**
|
|
72
78
|
* Run the generator on the environment and promises a RunResult instance.
|
|
73
79
|
* @return {PromiseRunResult} Promise a RunResult instance.
|
|
@@ -188,6 +194,7 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
188
194
|
* });
|
|
189
195
|
*/
|
|
190
196
|
withGenerators(dependencies: Dependency[]): this;
|
|
197
|
+
withMockedGeneratorFactory(mockedGeneratorFactory: MockedGeneratorFactory): this;
|
|
191
198
|
/**
|
|
192
199
|
* Create mocked generators
|
|
193
200
|
* @param namespaces - namespaces of mocked generators
|
|
@@ -210,10 +217,16 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
210
217
|
* @param localConfig - should look just like if called config.getAll()
|
|
211
218
|
*/
|
|
212
219
|
withLocalConfig(localConfig: Record<string, unknown>): this;
|
|
220
|
+
/**
|
|
221
|
+
* Don't reset mem-fs state cleared to aggregate snapshots from multiple runs.
|
|
222
|
+
*/
|
|
223
|
+
withKeepFsState(): this;
|
|
213
224
|
/**
|
|
214
225
|
* Add files to mem-fs.
|
|
215
226
|
* Files will be resolved relative to targetDir.
|
|
216
|
-
*
|
|
227
|
+
*
|
|
228
|
+
* Files with Object content will be merged to existing content.
|
|
229
|
+
* To avoid merging, `JSON.stringify` the content.
|
|
217
230
|
*/
|
|
218
231
|
withFiles(files: Record<string, string | Record<string, unknown>>): this;
|
|
219
232
|
withFiles(relativePath: string, files: Record<string, string | Record<string, unknown>>): this;
|
|
@@ -224,6 +237,10 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
224
237
|
* @returns
|
|
225
238
|
*/
|
|
226
239
|
withYoRc(content: string | Record<string, unknown>): this;
|
|
240
|
+
/**
|
|
241
|
+
* Add a generator config to .yo-rc.json
|
|
242
|
+
*/
|
|
243
|
+
withYoRcConfig(key: string, content: Record<string, unknown>): this;
|
|
227
244
|
/**
|
|
228
245
|
* Commit mem-fs files.
|
|
229
246
|
*/
|
|
@@ -246,6 +263,7 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
246
263
|
* @returns
|
|
247
264
|
*/
|
|
248
265
|
onEnvironment(callback: (this: this, env: Environment) => any): this;
|
|
266
|
+
prepare(): Promise<void>;
|
|
249
267
|
protected assertNotBuild(): void;
|
|
250
268
|
/**
|
|
251
269
|
* Build the generator and the environment.
|
|
@@ -257,6 +275,7 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
257
275
|
* @return Promise resolved on end or rejected on error
|
|
258
276
|
*/
|
|
259
277
|
protected toPromise(): PromiseRunResult<GeneratorType>;
|
|
278
|
+
protected _createRunResultOptions(): RunResultOptions<GeneratorType>;
|
|
260
279
|
/**
|
|
261
280
|
* Keeps compatibility with events
|
|
262
281
|
*/
|
|
@@ -269,12 +288,14 @@ export declare class RunContextBase<GeneratorType extends Generator = Generator>
|
|
|
269
288
|
* @return {this} run context instance
|
|
270
289
|
*/
|
|
271
290
|
private setDir;
|
|
272
|
-
private _createRunResultOptions;
|
|
273
291
|
}
|
|
274
|
-
export default class RunContext<GeneratorType extends Generator> extends RunContextBase<GeneratorType> implements Promise<RunResult<GeneratorType>> {
|
|
292
|
+
export default class RunContext<GeneratorType extends Generator = Generator> extends RunContextBase<GeneratorType> implements Promise<RunResult<GeneratorType>> {
|
|
275
293
|
then<TResult1 = RunResult<GeneratorType>, TResult2 = never>(onfulfilled?: ((value: RunResult<GeneratorType>) => TResult1 | PromiseLike<TResult1>) | undefined | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | undefined): Promise<TResult1 | TResult2>;
|
|
276
294
|
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | undefined): Promise<RunResult<GeneratorType> | TResult>;
|
|
277
295
|
finally(onfinally?: (() => void) | undefined | undefined): Promise<RunResult<GeneratorType>>;
|
|
278
296
|
get [Symbol.toStringTag](): string;
|
|
279
297
|
}
|
|
298
|
+
export declare class BasicRunContext extends RunContext {
|
|
299
|
+
run(): PromiseRunResult<any>;
|
|
300
|
+
}
|
|
280
301
|
export {};
|
package/dist/run-context.js
CHANGED
|
@@ -7,8 +7,12 @@ import process from 'node:process';
|
|
|
7
7
|
import _ from 'lodash';
|
|
8
8
|
import tempDirectory from 'temp-dir';
|
|
9
9
|
import MemFsEditor from 'mem-fs-editor';
|
|
10
|
+
import MemFsEditorState from 'mem-fs-editor/lib/state.js';
|
|
11
|
+
import MemFs from 'mem-fs';
|
|
10
12
|
import RunResult from './run-result.js';
|
|
11
13
|
import defaultHelpers from './helpers.js';
|
|
14
|
+
import testContext from './test-context.js';
|
|
15
|
+
const { camelCase, kebabCase, merge: lodashMerge, set: lodashSet } = _;
|
|
12
16
|
export class RunContextBase extends EventEmitter {
|
|
13
17
|
mockedGenerators = {};
|
|
14
18
|
env;
|
|
@@ -18,10 +22,13 @@ export class RunContextBase extends EventEmitter {
|
|
|
18
22
|
completed = false;
|
|
19
23
|
targetDirectory;
|
|
20
24
|
editor;
|
|
25
|
+
memFs;
|
|
26
|
+
mockedGeneratorFactory;
|
|
21
27
|
environmentPromise;
|
|
22
28
|
args = [];
|
|
23
29
|
options = {};
|
|
24
30
|
answers;
|
|
31
|
+
keepFsState;
|
|
25
32
|
onGeneratorCallbacks = [];
|
|
26
33
|
onTargetDirectoryCallbacks = [];
|
|
27
34
|
onEnvironmentCallbacks = [];
|
|
@@ -62,6 +69,8 @@ export class RunContextBase extends EventEmitter {
|
|
|
62
69
|
this.cd(this.settings.cwd);
|
|
63
70
|
}
|
|
64
71
|
this.helpers = helpers;
|
|
72
|
+
this.memFs = settings?.memFs ?? MemFs.create();
|
|
73
|
+
this.mockedGeneratorFactory = this.helpers.createMockedGenerator;
|
|
65
74
|
}
|
|
66
75
|
/**
|
|
67
76
|
* Run the generator on the environment and promises a RunResult instance.
|
|
@@ -79,7 +88,9 @@ export class RunContextBase extends EventEmitter {
|
|
|
79
88
|
this.helpers.restorePrompt(this.env);
|
|
80
89
|
this.completed = true;
|
|
81
90
|
}
|
|
82
|
-
|
|
91
|
+
const runResult = new RunResult(this._createRunResultOptions());
|
|
92
|
+
testContext.runResult = runResult;
|
|
93
|
+
return runResult;
|
|
83
94
|
}
|
|
84
95
|
// If any event listeners is added, setup event listeners emitters
|
|
85
96
|
on(eventName, listener) {
|
|
@@ -234,8 +245,8 @@ export class RunContextBase extends EventEmitter {
|
|
|
234
245
|
// Add options as both kebab and camel case. This is to stay backward compatibles with
|
|
235
246
|
// the switch we made to meow for options parsing.
|
|
236
247
|
for (const key of Object.keys(options)) {
|
|
237
|
-
options[
|
|
238
|
-
options[
|
|
248
|
+
options[camelCase(key)] = options[key];
|
|
249
|
+
options[kebabCase(key)] = options[key];
|
|
239
250
|
}
|
|
240
251
|
this.options = { ...this.options, ...options };
|
|
241
252
|
return this;
|
|
@@ -303,6 +314,10 @@ export class RunContextBase extends EventEmitter {
|
|
|
303
314
|
}
|
|
304
315
|
});
|
|
305
316
|
}
|
|
317
|
+
withMockedGeneratorFactory(mockedGeneratorFactory) {
|
|
318
|
+
this.mockedGeneratorFactory = mockedGeneratorFactory;
|
|
319
|
+
return this;
|
|
320
|
+
}
|
|
306
321
|
/**
|
|
307
322
|
* Create mocked generators
|
|
308
323
|
* @param namespaces - namespaces of mocked generators
|
|
@@ -321,7 +336,7 @@ export class RunContextBase extends EventEmitter {
|
|
|
321
336
|
*/
|
|
322
337
|
withMockedGenerators(namespaces) {
|
|
323
338
|
assert(Array.isArray(namespaces), 'namespaces should be an array');
|
|
324
|
-
const dependencies = namespaces.map(namespace => [this.
|
|
339
|
+
const dependencies = namespaces.map(namespace => [this.mockedGeneratorFactory(), namespace]);
|
|
325
340
|
const entries = dependencies.map(([generator, namespace]) => [namespace, generator]);
|
|
326
341
|
Object.assign(this.mockedGenerators, Object.fromEntries(entries));
|
|
327
342
|
return this.withGenerators(dependencies);
|
|
@@ -334,6 +349,13 @@ export class RunContextBase extends EventEmitter {
|
|
|
334
349
|
assert(typeof localConfig === 'object', 'config should be an object');
|
|
335
350
|
return this.onGenerator(generator => generator.config.defaults(localConfig));
|
|
336
351
|
}
|
|
352
|
+
/**
|
|
353
|
+
* Don't reset mem-fs state cleared to aggregate snapshots from multiple runs.
|
|
354
|
+
*/
|
|
355
|
+
withKeepFsState() {
|
|
356
|
+
this.keepFsState = true;
|
|
357
|
+
return this;
|
|
358
|
+
}
|
|
337
359
|
withFiles(relativePath, files) {
|
|
338
360
|
return this.onTargetDirectory(function () {
|
|
339
361
|
const targetDirectory = typeof relativePath === 'string' ? pathJoin(this.targetDirectory, relativePath) : this.targetDirectory;
|
|
@@ -346,7 +368,8 @@ export class RunContextBase extends EventEmitter {
|
|
|
346
368
|
this.editor.write(resolvedFile, content);
|
|
347
369
|
}
|
|
348
370
|
else {
|
|
349
|
-
this.editor.
|
|
371
|
+
const fileContent = this.editor.readJSON(resolvedFile, {});
|
|
372
|
+
this.editor.writeJSON(resolvedFile, lodashMerge(fileContent, content));
|
|
350
373
|
}
|
|
351
374
|
}
|
|
352
375
|
});
|
|
@@ -362,6 +385,13 @@ export class RunContextBase extends EventEmitter {
|
|
|
362
385
|
'.yo-rc.json': content,
|
|
363
386
|
});
|
|
364
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Add a generator config to .yo-rc.json
|
|
390
|
+
*/
|
|
391
|
+
withYoRcConfig(key, content) {
|
|
392
|
+
const yoRcContent = lodashSet({}, key, content);
|
|
393
|
+
return this.withYoRc(yoRcContent);
|
|
394
|
+
}
|
|
365
395
|
/**
|
|
366
396
|
* Commit mem-fs files.
|
|
367
397
|
*/
|
|
@@ -400,16 +430,7 @@ export class RunContextBase extends EventEmitter {
|
|
|
400
430
|
this.onEnvironmentCallbacks.push(callback);
|
|
401
431
|
return this;
|
|
402
432
|
}
|
|
403
|
-
|
|
404
|
-
if (this.built || this.completed) {
|
|
405
|
-
throw new Error('The context is already built');
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Build the generator and the environment.
|
|
410
|
-
* @return {RunContext|false} this
|
|
411
|
-
*/
|
|
412
|
-
async build() {
|
|
433
|
+
async prepare() {
|
|
413
434
|
this.assertNotBuild();
|
|
414
435
|
this.built = true;
|
|
415
436
|
if (!this.targetDirectory && this.settings.tmpdir !== false) {
|
|
@@ -428,17 +449,36 @@ export class RunContextBase extends EventEmitter {
|
|
|
428
449
|
if (!this.targetDirectory) {
|
|
429
450
|
throw new Error('targetDirectory is required');
|
|
430
451
|
}
|
|
452
|
+
if (!this.keepFsState) {
|
|
453
|
+
this.memFs.each(file => {
|
|
454
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
455
|
+
delete file[MemFsEditorState.STATE_CLEARED];
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
this.editor = MemFsEditor.create(this.memFs);
|
|
459
|
+
for (const onTargetDirectory of this.onTargetDirectoryCallbacks) {
|
|
460
|
+
// eslint-disable-next-line no-await-in-loop
|
|
461
|
+
await onTargetDirectory.call(this, this.targetDirectory);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
assertNotBuild() {
|
|
465
|
+
if (this.built || this.completed) {
|
|
466
|
+
throw new Error('The context is already built');
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Build the generator and the environment.
|
|
471
|
+
* @return {RunContext|false} this
|
|
472
|
+
*/
|
|
473
|
+
async build() {
|
|
474
|
+
await this.prepare();
|
|
431
475
|
const testEnv = await this.helpers.createTestEnv(this.envOptions.createEnv, {
|
|
432
476
|
cwd: this.settings.forwardCwd ? this.targetDirectory : undefined,
|
|
477
|
+
sharedFs: this.memFs,
|
|
433
478
|
...this.options,
|
|
434
479
|
...this.envOptions,
|
|
435
480
|
});
|
|
436
481
|
this.env = this.envCB ? (await this.envCB(testEnv)) ?? testEnv : testEnv;
|
|
437
|
-
this.editor = MemFsEditor.create(this.env.sharedFs);
|
|
438
|
-
for (const onTargetDirectory of this.onTargetDirectoryCallbacks) {
|
|
439
|
-
// eslint-disable-next-line no-await-in-loop
|
|
440
|
-
await onTargetDirectory.call(this, this.targetDirectory);
|
|
441
|
-
}
|
|
442
482
|
for (const onEnvironmentCallback of this.onEnvironmentCallbacks) {
|
|
443
483
|
// eslint-disable-next-line no-await-in-loop
|
|
444
484
|
await onEnvironmentCallback.call(this, this.env);
|
|
@@ -466,6 +506,21 @@ export class RunContextBase extends EventEmitter {
|
|
|
466
506
|
async toPromise() {
|
|
467
507
|
return this.environmentPromise ?? this.run();
|
|
468
508
|
}
|
|
509
|
+
_createRunResultOptions() {
|
|
510
|
+
return {
|
|
511
|
+
env: this.env,
|
|
512
|
+
generator: this.generator,
|
|
513
|
+
memFs: this.env?.sharedFs ?? this.memFs,
|
|
514
|
+
settings: {
|
|
515
|
+
...this.settings,
|
|
516
|
+
},
|
|
517
|
+
oldCwd: this.oldCwd,
|
|
518
|
+
cwd: this.targetDirectory,
|
|
519
|
+
envOptions: this.envOptions,
|
|
520
|
+
mockedGenerators: this.mockedGenerators,
|
|
521
|
+
helpers: this.helpers,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
469
524
|
/**
|
|
470
525
|
* Keeps compatibility with events
|
|
471
526
|
*/
|
|
@@ -513,21 +568,6 @@ export class RunContextBase extends EventEmitter {
|
|
|
513
568
|
this.targetDirectory = dirPath;
|
|
514
569
|
return this;
|
|
515
570
|
}
|
|
516
|
-
_createRunResultOptions() {
|
|
517
|
-
return {
|
|
518
|
-
env: this.env,
|
|
519
|
-
generator: this.generator,
|
|
520
|
-
memFs: this.env.sharedFs,
|
|
521
|
-
settings: {
|
|
522
|
-
...this.settings,
|
|
523
|
-
},
|
|
524
|
-
oldCwd: this.oldCwd,
|
|
525
|
-
cwd: this.targetDirectory,
|
|
526
|
-
envOptions: this.envOptions,
|
|
527
|
-
mockedGenerators: this.mockedGenerators,
|
|
528
|
-
helpers: this.helpers,
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
571
|
}
|
|
532
572
|
export default class RunContext extends RunContextBase {
|
|
533
573
|
// eslint-disable-next-line unicorn/no-thenable
|
|
@@ -544,3 +584,11 @@ export default class RunContext extends RunContextBase {
|
|
|
544
584
|
return `RunContext`;
|
|
545
585
|
}
|
|
546
586
|
}
|
|
587
|
+
export class BasicRunContext extends RunContext {
|
|
588
|
+
async run() {
|
|
589
|
+
await this.prepare();
|
|
590
|
+
const runResult = new RunResult(this._createRunResultOptions());
|
|
591
|
+
testContext.runResult = runResult;
|
|
592
|
+
return runResult;
|
|
593
|
+
}
|
|
594
|
+
}
|
package/dist/run-result.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export type RunResultOptions<GeneratorType extends Generator> = {
|
|
|
37
37
|
/**
|
|
38
38
|
* This class provides utilities for testing generated content.
|
|
39
39
|
*/
|
|
40
|
-
export default class RunResult<GeneratorType extends Generator> {
|
|
40
|
+
export default class RunResult<GeneratorType extends Generator = Generator> {
|
|
41
41
|
env: any;
|
|
42
42
|
generator: GeneratorType;
|
|
43
43
|
cwd: string;
|
package/dist/run-result.js
CHANGED
|
@@ -45,9 +45,10 @@ export default class RunResult {
|
|
|
45
45
|
...this.options.settings,
|
|
46
46
|
cwd: this.cwd,
|
|
47
47
|
oldCwd: this.oldCwd,
|
|
48
|
+
memFs: this.memFs,
|
|
48
49
|
...settings,
|
|
49
50
|
autoCleanup: false,
|
|
50
|
-
}, { ...this.options.envOptions,
|
|
51
|
+
}, { ...this.options.envOptions, ...envOptions });
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
53
54
|
* Return an object with fs changes.
|
package/dist/test-context.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type RunContext from './run-context.js';
|
|
2
|
+
import type RunResult from './run-result.js';
|
|
2
3
|
declare class TestContext {
|
|
4
|
+
runResult?: RunResult;
|
|
3
5
|
private runContext?;
|
|
4
6
|
startNewContext(runContext: RunContext<any>): void;
|
|
5
7
|
}
|
|
6
|
-
declare const
|
|
7
|
-
export default
|
|
8
|
+
declare const testContext: TestContext;
|
|
9
|
+
export default testContext;
|
|
10
|
+
/**
|
|
11
|
+
* Provides a proxy for last executed context result.
|
|
12
|
+
*/
|
|
13
|
+
export declare const result: RunResult;
|
package/dist/test-context.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
class TestContext {
|
|
2
|
+
runResult;
|
|
2
3
|
runContext;
|
|
3
4
|
startNewContext(runContext) {
|
|
4
5
|
this.runContext?.cleanupTemporaryDir();
|
|
5
6
|
this.runContext = runContext;
|
|
7
|
+
this.runResult = undefined;
|
|
6
8
|
}
|
|
7
9
|
}
|
|
8
|
-
|
|
10
|
+
const testContext = new TestContext();
|
|
11
|
+
export default testContext;
|
|
12
|
+
const handler2 = {
|
|
13
|
+
get(_target, prop, receiver) {
|
|
14
|
+
if (testContext.runResult === undefined) {
|
|
15
|
+
throw new Error('Last result is missing.');
|
|
16
|
+
}
|
|
17
|
+
return Reflect.get(testContext.runResult, prop, receiver);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Provides a proxy for last executed context result.
|
|
22
|
+
*/
|
|
23
|
+
export const result = new Proxy({}, handler2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yeoman-test",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"description": "Test utilities for Yeoman generators",
|
|
5
5
|
"homepage": "http://yeoman.io/authoring/testing.html",
|
|
6
6
|
"author": "The Yeoman Team",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@types/yeoman-generator": "^5.2.11",
|
|
52
52
|
"inquirer": "^8.2.5",
|
|
53
53
|
"lodash": "^4.17.21",
|
|
54
|
-
"mem-fs-editor": "^9.
|
|
54
|
+
"mem-fs-editor": "^9.7.0",
|
|
55
55
|
"sinon": "^14.0.2",
|
|
56
56
|
"temp-dir": "^3.0.0"
|
|
57
57
|
},
|