diff --git a/src/run-context.ts b/src/run-context.ts index eb90ee2..573f4fd 100644 --- a/src/run-context.ts +++ b/src/run-context.ts @@ -10,6 +10,8 @@ import type Generator from 'yeoman-generator'; import type Environment from 'yeoman-environment'; import { type LookupOptions, type Options } from 'yeoman-environment'; import MemFsEditor from 'mem-fs-editor'; +import MemFsEditorState from 'mem-fs-editor/lib/state.js'; +import MemFs from 'mem-fs'; import RunResult, { type RunResultOptions } from './run-result.js'; import defaultHelpers, { type GeneratorConstructor, type Dependency, type YeomanTest } from './helpers.js'; @@ -35,6 +37,8 @@ export type RunContextSettings = { autoCleanup?: boolean; + memFs?: MemFs.Store; + /** * File path to the generator (only used if Generator is a constructor) */ @@ -58,12 +62,14 @@ export class RunContextBase extends completed = false; targetDirectory?: string; editor!: MemFsEditor.Editor; + memFs: MemFs.Store; protected environmentPromise?: PromiseRunResult; private args: string[] = []; private options: any = {}; private answers?: any; + private keepFsState?: boolean; private readonly onGeneratorCallbacks: Array<(this: this, generator: GeneratorType) => any> = []; @@ -120,6 +126,7 @@ export class RunContextBase extends } this.helpers = helpers; + this.memFs = settings?.memFs ?? MemFs.create(); } /** @@ -421,6 +428,14 @@ export class RunContextBase extends return this.onGenerator(generator => generator.config.defaults(localConfig)); } + /** + * Don't reset mem-fs state cleared to aggregate snapshots from multiple runs. + */ + withKeepFsState(): this { + this.keepFsState = true; + return this; + } + /** * Add files to mem-fs. * Files will be resolved relative to targetDir. @@ -548,20 +563,28 @@ export class RunContextBase extends throw new Error('targetDirectory is required'); } - const testEnv = await this.helpers.createTestEnv(this.envOptions.createEnv, { - cwd: this.settings.forwardCwd ? this.targetDirectory : undefined, - ...this.options, - ...this.envOptions, - }); - this.env = this.envCB ? (await this.envCB(testEnv)) ?? testEnv : testEnv; + if (!this.keepFsState) { + this.memFs.each(file => { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete file[MemFsEditorState.STATE_CLEARED]; + }); + } - this.editor = MemFsEditor.create(this.env.sharedFs); + this.editor = MemFsEditor.create(this.memFs); for (const onTargetDirectory of this.onTargetDirectoryCallbacks) { // eslint-disable-next-line no-await-in-loop await onTargetDirectory.call(this, this.targetDirectory); } + const testEnv = await this.helpers.createTestEnv(this.envOptions.createEnv, { + cwd: this.settings.forwardCwd ? this.targetDirectory : undefined, + sharedFs: this.memFs, + ...this.options, + ...this.envOptions, + }); + this.env = this.envCB ? (await this.envCB(testEnv)) ?? testEnv : testEnv; + for (const onEnvironmentCallback of this.onEnvironmentCallbacks) { // eslint-disable-next-line no-await-in-loop await onEnvironmentCallback.call(this, this.env); diff --git a/src/run-result.ts b/src/run-result.ts index 5d5d952..1c68c8e 100644 --- a/src/run-result.ts +++ b/src/run-result.ts @@ -102,10 +102,11 @@ export default class RunResult { ...this.options.settings, cwd: this.cwd, oldCwd: this.oldCwd, + memFs: this.memFs, ...settings, autoCleanup: false, }, - { ...this.options.envOptions, memFs: this.memFs, ...envOptions }, + { ...this.options.envOptions, ...envOptions }, ); } diff --git a/test/run-context-environment.spec.ts b/test/run-context-environment.spec.ts index f565125..f44b3db 100644 --- a/test/run-context-environment.spec.ts +++ b/test/run-context-environment.spec.ts @@ -68,6 +68,12 @@ describe('RunContext running environment', function () { }); }); + it('forwards the mem-fs to the environment', () => { + return ctx.run().then(() => { + assert.equal(ctx.memFs, ctx.env.sharedFs); + }); + }); + it('passes newErrorHandler to the environment', () => { return ctx.run().then(() => { assert(ctx.env.options.newErrorHandler); diff --git a/test/run-result.spec.ts b/test/run-result.spec.ts index 67fd7ac..cfe2743 100644 --- a/test/run-result.spec.ts +++ b/test/run-result.spec.ts @@ -234,8 +234,8 @@ describe('run-result', () => { it('forwards oldCwd from the original RunResult', () => { assert.equal(runContext.oldCwd, oldCwd); }); - it('forwards memFs from the original RunResult to new envOptions', () => { - assert.equal(runContext.envOptions.memFs, memFs); + it('forwards memFs from the original RunResult to new RunContext', () => { + assert.equal(runContext.memFs, memFs); }); it('prefers settings passed to the method', () => { assert.equal(runContext.settings.overrided, 'newOverrided');