UNPKG

12.9 kBTypeScriptView Raw
1import { EventEmitter } from 'node:events';
2import { mock } from 'node:test';
3import { type Store } from 'mem-fs';
4import type { BaseEnvironmentOptions, BaseGenerator, GetGeneratorConstructor, GetGeneratorOptions, LookupOptions, PromptAnswers } from '@yeoman/types';
5import { type MemFsEditor, type MemFsEditorFile } from 'mem-fs-editor';
6import type { DefaultEnvironmentApi, DefaultGeneratorApi } from '../types/type-helpers.js';
7import RunResult, { type RunResultOptions } from './run-result.js';
8import { type CreateEnv as CreateEnvironment, type Dependency, type YeomanTest } from './helpers.js';
9import { type AskedQuestions, type DummyPromptOptions, type TestAdapterOptions } from './adapter.js';
10/**
11 * Provides settings for creating a `RunContext`.
12 */
13export type RunContextSettings = {
14 /**
15 * Automatically run this generator in a tmp dir
16 * @default true
17 */
18 tmpdir?: boolean;
19 cwd?: string;
20 oldCwd?: string;
21 forwardCwd?: boolean;
22 autoCleanup?: boolean;
23 memFs?: Store<MemFsEditorFile>;
24 /**
25 * File path to the generator (only used if Generator is a constructor)
26 */
27 resolved?: string;
28 /**
29 * Namespace (only used if Generator is a constructor)
30 * @default 'gen:test'
31 */
32 namespace?: string;
33};
34type PromiseRunResult<GeneratorType extends BaseGenerator> = Promise<RunResult<GeneratorType>>;
35type MockedGeneratorFactory<GenParameter extends BaseGenerator = DefaultGeneratorApi> = (GeneratorClass?: GetGeneratorConstructor<GenParameter>) => GetGeneratorConstructor<GenParameter>;
36type EnvironmentOptions = BaseEnvironmentOptions & {
37 createEnv?: CreateEnvironment;
38};
39export declare class RunContextBase<GeneratorType extends BaseGenerator = DefaultGeneratorApi> extends EventEmitter {
40 readonly mockedGenerators: Record<string, BaseGenerator>;
41 env: DefaultEnvironmentApi;
42 generator: GeneratorType;
43 readonly settings: RunContextSettings;
44 readonly envOptions: EnvironmentOptions;
45 completed: boolean;
46 targetDirectory?: string;
47 editor: MemFsEditor;
48 memFs: Store<MemFsEditorFile>;
49 spawnStub?: any;
50 mockedGeneratorFactory: MockedGeneratorFactory;
51 readonly askedQuestions: AskedQuestions;
52 protected environmentPromise?: PromiseRunResult<GeneratorType>;
53 private args;
54 private options;
55 private answers?;
56 private readonly adapterOptions?;
57 private keepFsState?;
58 private readonly onGeneratorCallbacks;
59 private readonly onTargetDirectoryCallbacks;
60 private readonly onEnvironmentCallbacks;
61 private readonly inDirCallbacks;
62 private readonly Generator?;
63 private readonly helpers;
64 private readonly temporaryDir;
65 private oldCwd?;
66 private eventListenersSet;
67 private envCB;
68 private built;
69 private ran;
70 private errored;
71 private readonly beforePrepareCallbacks;
72 private environmentRun?;
73 /**
74 * This class provide a run context object to façade the complexity involved in setting
75 * up a generator for testing
76 * @constructor
77 * @param Generator - Namespace or generator constructor. If the later
78 * is provided, then namespace is assumed to be
79 * 'gen:test' in all cases
80 * @param settings
81 * @return {this}
82 */
83 constructor(generatorType?: string | GetGeneratorConstructor<GeneratorType>, settings?: RunContextSettings, environmentOptions?: EnvironmentOptions, helpers?: YeomanTest);
84 /**
85 * Run the generator on the environment and promises a RunResult instance.
86 * @return {PromiseRunResult} Promise a RunResult instance.
87 */
88 run(): PromiseRunResult<GeneratorType>;
89 on(eventName: string | symbol, listener: (...arguments_: any[]) => void): this;
90 /**
91 * @deprecated
92 * Clean the provided directory, then change directory into it
93 * @param dirPath - Directory path (relative to CWD). Prefer passing an absolute
94 * file path for predictable results
95 * @param [cb] - callback who'll receive the folder path as argument
96 * @return run context instance
97 */
98 inDir(dirPath: string, callback?: (folderPath: string) => void): this;
99 /**
100 * Register an callback to prepare the destination folder.
101 * @param [cb] - callback who'll receive the folder path as argument
102 * @return this - run context instance
103 */
104 doInDir(callback: (folderPath: string) => void): this;
105 /**
106 * @deprecated
107 * Change directory without deleting directory content.
108 * @param dirPath - Directory path (relative to CWD). Prefer passing an absolute
109 * file path for predictable results
110 * @return run context instance
111 */
112 cd(dirPath: string): this;
113 /**
114 * Cleanup a temporary directory and change the CWD into it
115 *
116 * This method is called automatically when creating a RunContext. Only use it if you need
117 * to use the callback.
118 *
119 * @param [cb] - callback who'll receive the folder path as argument
120 * @return this - run context instance
121 */
122 inTmpDir(callback?: (folderPath: string) => void): this;
123 /**
124 * Restore cwd to initial cwd.
125 * @return {this} run context instance
126 */
127 restore(): this;
128 /**
129 * Clean the directory used for tests inside inDir/inTmpDir
130 * @param {Boolean} force - force directory cleanup for not tmpdir
131 */
132 cleanup(): void;
133 /**
134 * Clean the directory used for tests inside inDir/inTmpDir
135 * @param {Boolean} force - force directory cleanup for not tmpdir
136 */
137 cleanupTemporaryDir(): void;
138 /**
139 * Clean the directory used for tests inside inDir/inTmpDir
140 * @param force - force directory cleanup for not tmpdir
141 */
142 cleanTestDirectory(force?: boolean): void;
143 /**
144 * TestAdapter options.
145 */
146 withAdapterOptions(options: Omit<TestAdapterOptions, 'mockedAnswers'>): this;
147 /**
148 * Create an environment
149 *
150 * This method is called automatically when creating a RunContext. Only use it if you need
151 * to use the callback.
152 *
153 * @param {Function} [cb] - callback who'll receive the folder path as argument
154 * @return {this} run context instance
155 */
156 withEnvironment(callback: any): this;
157 /**
158 * Customize enviroment run method.
159 *
160 * @param callback
161 * @return {this} run context instance
162 */
163 withEnvironmentRun(callback: (this: this, env: DefaultEnvironmentApi, gen: GeneratorType) => void): this;
164 /**
165 * Run lookup on the environment.
166 *
167 * @param lookups - lookup to run.
168 */
169 withLookups(lookups: LookupOptions | LookupOptions[]): this;
170 /**
171 * Provide arguments to the run context
172 * @param args - command line arguments as Array or space separated string
173 */
174 withArguments(arguments_: string | string[]): this;
175 /**
176 * Provide options to the run context
177 * @param {Object} options - command line options (e.g. `--opt-one=foo`)
178 * @return {this}
179 */
180 withOptions(options: Partial<Omit<GetGeneratorOptions<GeneratorType>, 'env' | 'namespace' | 'resolved'>>): this;
181 /**
182 * @deprecated
183 * Mock the prompt with dummy answers
184 * @param answers - Answers to the prompt questions
185 * @param options - Options or callback.
186 * @param {Function} [options.callback] - Callback.
187 * @param {Boolean} [options.throwOnMissingAnswer] - Throw if a answer is missing.
188 * @return {this}
189 */
190 withPrompts(answers: PromptAnswers, options?: Omit<DummyPromptOptions, 'mockedAnswers'>): this;
191 /**
192 * Mock answers for prompts
193 * @param answers - Answers to the prompt questions
194 * @param options - Options or callback.
195 * @return {this}
196 */
197 withAnswers(answers: PromptAnswers, options?: Omit<DummyPromptOptions, 'mockedAnswers'>): this;
198 /**
199 * Provide dependent generators
200 * @param {Array} dependencies - paths to the generators dependencies
201 * @return {this}
202 * @example
203 * var angular = new RunContext('../../app');
204 * angular.withGenerators([
205 * '../../common',
206 * '../../controller',
207 * '../../main',
208 * [helpers.createDummyGenerator(), 'testacular:app']
209 * ]);
210 * angular.on('end', function () {
211 * // assert something
212 * });
213 */
214 withGenerators(dependencies: Dependency[]): this;
215 withSpawnMock<StubType = ReturnType<typeof mock.fn>>(options?: ((...arguments_: any[]) => any) | {
216 stub?: (...arguments_: any[]) => any;
217 registerNodeMockDefaults?: boolean;
218 callback?: ({ stub, implementation }: {
219 stub: StubType;
220 implementation: any;
221 }) => void | Promise<void>;
222 }): this;
223 withMockedGeneratorFactory(mockedGeneratorFactory: MockedGeneratorFactory): this;
224 /**
225 * Create mocked generators
226 * @param namespaces - namespaces of mocked generators
227 * @return this
228 * @example
229 * var angular = helpers
230 * .create('../../app')
231 * .withMockedGenerators([
232 * 'foo:app',
233 * 'foo:bar',
234 * ])
235 * .run()
236 * .then(runResult => assert(runResult
237 * .mockedGenerators['foo:app']
238 .calledOnce));
239 */
240 withMockedGenerators(namespaces: string[]): this;
241 /**
242 * Mock the local configuration with the provided config
243 * @param localConfig - should look just like if called config.getAll()
244 */
245 withLocalConfig(localConfig: any): this;
246 /**
247 * Don't reset mem-fs state cleared to aggregate snapshots from multiple runs.
248 */
249 withKeepFsState(): this;
250 /**
251 * Add files to mem-fs.
252 * Files will be resolved relative to targetDir.
253 *
254 * Files with Object content will be merged to existing content.
255 * To avoid merging, `JSON.stringify` the content.
256 */
257 withFiles(files: Record<string, string | Record<string, unknown>>): this;
258 withFiles(relativePath: string, files: Record<string, string | Record<string, unknown>>): this;
259 /**
260 * Add .yo-rc.json to mem-fs.
261 *
262 * @param content
263 * @returns
264 */
265 withYoRc(content: string | Record<string, unknown>): this;
266 /**
267 * Add a generator config to .yo-rc.json
268 */
269 withYoRcConfig(key: string, content: Record<string, unknown>): this;
270 /**
271 * Commit mem-fs files.
272 */
273 commitFiles(): this;
274 /**
275 * Execute callback after targetDirectory is set
276 * @param callback
277 * @returns
278 */
279 onTargetDirectory(callback: (this: this, targetDirectory: string) => any): this;
280 /**
281 * Execute callback after generator is ready
282 * @param callback
283 * @returns
284 */
285 onGenerator(callback: (this: this, generator: GeneratorType) => any): this;
286 /**
287 * Execute callback prefore parepare
288 * @param callback
289 * @returns
290 */
291 onBeforePrepare(callback: (this: this) => void | Promise<void>): this;
292 /**
293 * Execute callback after environment is ready
294 * @param callback
295 * @returns
296 */
297 onEnvironment(callback: (this: this, environment: DefaultEnvironmentApi) => any): this;
298 prepare(): Promise<void>;
299 protected assertNotBuild(): void;
300 /**
301 * Build the generator and the environment.
302 * @return {RunContext|false} this
303 */
304 build(): Promise<void>;
305 /**
306 * Return a promise representing the generator run process
307 * @return Promise resolved on end or rejected on error
308 */
309 protected toPromise(): PromiseRunResult<GeneratorType>;
310 protected _createRunResultOptions(): RunResultOptions<GeneratorType>;
311 /**
312 * Keeps compatibility with events
313 */
314 private setupEventListeners;
315 /**
316 * Set the target directory.
317 * @private
318 * @param {String} dirPath - Directory path (relative to CWD). Prefer passing an absolute
319 * file path for predictable results
320 * @return {this} run context instance
321 */
322 private setDir;
323}
324export default class RunContext<GeneratorType extends BaseGenerator = BaseGenerator> extends RunContextBase<GeneratorType> implements Promise<RunResult<GeneratorType>> {
325 then<TResult1 = RunResult<GeneratorType>, TResult2 = never>(onfulfilled?: ((value: RunResult<GeneratorType>) => TResult1 | PromiseLike<TResult1>) | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined): Promise<TResult1 | TResult2>;
326 catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined): Promise<RunResult<GeneratorType> | TResult>;
327 finally(onfinally?: (() => void) | undefined): Promise<RunResult<GeneratorType>>;
328 get [Symbol.toStringTag](): string;
329}
330export declare class BasicRunContext<GeneratorType extends BaseGenerator = BaseGenerator> extends RunContext<GeneratorType> {
331 run(): PromiseRunResult<any>;
332}
333export {};
334
\No newline at end of file