Skip to content

Commit

Permalink
add options to withSpawnMock
Browse files Browse the repository at this point in the history
  • Loading branch information
mshima committed Oct 26, 2023
1 parent ad379b0 commit d6f2666
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 7 deletions.
30 changes: 28 additions & 2 deletions src/run-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { camelCase, kebabCase, merge as lodashMerge, set as lodashSet } from 'lo
import { resetFileCommitStates } from 'mem-fs-editor/state';
import { create as createMemFs, type Store } from 'mem-fs';
import tempDirectory from 'temp-dir';
import { stub as sinonStub } from 'sinon';
import { stub as sinonStub, type SinonStub } from 'sinon';
import type {
BaseEnvironmentOptions,
BaseGenerator,
Expand Down Expand Up @@ -407,11 +407,37 @@ export class RunContextBase<GeneratorType extends BaseGenerator = DefaultGenerat
});
}

withSpawnMock(stub = sinonStub()): this {
withSpawnMock(
options?: ((...args) => any) | { stub?: (...args) => any; registerSinonDefaults?: boolean; callback?: (stub) => void | Promise<void> },
): this {
if (this.spawnStub) {
throw new Error('Multiple withSpawnMock calls');
}

const stub = typeof options === 'function' ? options : options?.stub ?? sinonStub();
const registerSinonDefaults = typeof options === 'function' ? false : options?.registerSinonDefaults ?? true;
const callback = typeof options === 'function' ? undefined : options?.callback;

if (registerSinonDefaults) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
const defaultChild = { stdout: { on() {} }, stderr: { on() {} } };
const defaultReturn = { exitCode: 0, stdout: '', stderr: '' };
const stubFn = stub as SinonStub;

// eslint-disable-next-line @typescript-eslint/promise-function-async
stubFn.withArgs('spawnCommand').callsFake(() => Object.assign(Promise.resolve({ ...defaultReturn }), defaultChild));
// eslint-disable-next-line @typescript-eslint/promise-function-async
stubFn.withArgs('spawn').callsFake(() => Object.assign(Promise.resolve({ ...defaultReturn }), defaultChild));
stubFn.withArgs('spawnCommandSync').callsFake(() => ({ ...defaultReturn }));
stubFn.withArgs('spawnSync').callsFake(() => ({ ...defaultReturn }));
}

if (callback) {
this.onBeforePrepare(async () => {
await callback(stub);
});
}

this.spawnStub = stub;
return this.onEnvironment(env => {
env.on('compose', (_namespace, generator) => {
Expand Down
47 changes: 42 additions & 5 deletions test/run-context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url';
import process from 'node:process';
import { createRequire } from 'node:module';
import { expect } from 'esmocha';
import { assert as sinonAssert, spy as sinonSpy, stub as sinonStub, fake as sinonFake } from 'sinon';
import { assert as sinonAssert, spy as sinonSpy, stub as sinonStub, fake as sinonFake, type SinonStub } from 'sinon';
import inquirer from 'inquirer';
import Generator from 'yeoman-generator';
import tempDirectory from 'temp-dir';
Expand Down Expand Up @@ -647,10 +647,17 @@ describe('RunContext', function () {
it('provide arguments to the generator when passed as String', async function () {
ctx.withSpawnMock();
Dummy.prototype.mockTask = async function () {
await this.spawnCommand('foo');
this.spawnCommandSync('foo');
await this.spawn('foo');
this.spawnSync('foo');
const spawnCommandFoo = this.spawnCommand('foo');
expect(spawnCommandFoo).toMatchObject({ stderr: expect.any(Object), stdout: expect.any(Object) });
await expect(spawnCommandFoo).resolves.toMatchObject({ exitCode: 0, stderr: '', stdout: '' });

expect(this.spawnCommandSync('foo')).toMatchObject({ exitCode: 0, stderr: '', stdout: '' });

const spawnFoo = this.spawn('foo');
expect(spawnFoo).toMatchObject({ stderr: expect.any(Object), stdout: expect.any(Object) });
await expect(spawnFoo).resolves.toMatchObject({ exitCode: 0, stderr: '', stdout: '' });

expect(this.spawnSync('foo')).toMatchObject({ exitCode: 0, stderr: '', stdout: '' });
};

const result = await ctx.toPromise();
Expand All @@ -659,6 +666,36 @@ describe('RunContext', function () {
assert.deepStrictEqual(result.getSpawnArgsUsingDefaultImplementation()[2], ['spawn', 'foo']);
assert.deepStrictEqual(result.getSpawnArgsUsingDefaultImplementation()[3], ['spawnSync', 'foo']);
});

it('with callback', async function () {
ctx.withSpawnMock({
stub: sinonStub(),
registerSinonDefaults: true,
callback(stub: SinonStub) {
stub.withArgs('spawnCommandSync', 'foo').returns('bar');
},
});

Dummy.prototype.mockTask = async function () {
expect(this.spawnCommandSync()).toMatchObject({ exitCode: 0, stderr: '', stdout: '' });
expect(this.spawnCommandSync('foo')).toBe('bar');
};

await ctx.toPromise();
});

it('without defaults', async function () {
ctx.withSpawnMock({
stub: sinonStub(),
registerSinonDefaults: false,
});

Dummy.prototype.mockTask = async function () {
expect(this.spawnCommandSync()).toBeUndefined();
};

await ctx.toPromise();
});
});

describe('#withEnvironment()', function () {
Expand Down

0 comments on commit d6f2666

Please sign in to comment.