diff --git a/test/spawn-command.test.ts b/test/spawn-command.test.ts index 1b2aaec7..063d0c68 100644 --- a/test/spawn-command.test.ts +++ b/test/spawn-command.test.ts @@ -1,16 +1,17 @@ +import assert from 'node:assert'; import { expect, mock, restoreAllMocks, fn, importMock } from 'esmocha'; +import { spy } from 'sinon'; const execa = await mock('execa'); const { default: Generator } = await importMock('../src/index.js', { execa }); describe('generators.Base (actions/spawn-command)', () => { - let cwd; - let spawn; + let testGenerator: Generator; beforeEach(async function () { - spawn = new Generator({ help: true, namespace: 'foo', resolved: 'unknown' }); - cwd = Math.random().toString(36).slice(7); - spawn.destinationRoot = fn().mockReturnValue(cwd); + testGenerator = new Generator({ help: true, namespace: 'foo', resolved: 'unknown' }); + // @ts-expect-error We are explicitly setting the function to a mocked function. We know .destinationRoot exists on the generator. + testGenerator.destinationRoot = fn().mockReturnValue('some/destination/path'); }); afterEach(() => { @@ -18,70 +19,160 @@ describe('generators.Base (actions/spawn-command)', () => { }); describe('#spawnCommand()', () => { - it('provide default options', async function () { - await spawn.spawnCommand('foo'); - expect(execa.execaCommand).toHaveBeenCalledWith('foo', { - cwd, - stdio: 'inherit', + describe('only the command is required', () => { + describe('no args and no options are given', () => { + it('calls execaCommandSync with the command, {stdio: "inherit", cwd: this.destinationRoot()}', () => { + // @ts-expect-error We know that spawnCommand exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommand('foo'); + expect(execa.execaCommand).toHaveBeenCalledWith('foo', { + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), + stdio: 'inherit', + }); + }); }); }); - it('pass arguments', async function () { - await spawn.spawnCommand('foo', ['bar']); - expect(execa.execa).toHaveBeenCalledWith('foo', ['bar'], { - cwd, - stdio: 'inherit', + describe('calls spawn if args and/or opts are given', () => { + it('args given are passed to spawnSync', () => { + // @ts-expect-error We know that spawn exists on the generator. It is added with applyMixins(). + const spawnSpy = spy(testGenerator, 'spawn'); + // @ts-expect-error We know that spawnCommand exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommand('foo', ['bar']); + // @ts-expect-error TypeScript doesn't like the args type for .calledWith + assert.ok(spawnSpy.calledWith('foo', ['bar'], undefined)); + }); + it('opts given are passed to spawnSync', () => { + // @ts-expect-error We know that spawn exists on the generator. It is added with applyMixins(). + const spawnSpy = spy(testGenerator, 'spawn'); + // @ts-expect-error We know that spawnCommand exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommand('foo', undefined, { verbose: true }); + // @ts-expect-error TypeScript doesn't like the args type for .calledWith + assert.ok(spawnSpy.calledWith('foo', undefined, { verbose: true })); + }); + it('both args and opts given are passed to spawnSync', () => { + // @ts-expect-error We know that spawn exists on the generator. It is added with applyMixins(). + const spawnSpy = spy(testGenerator, 'spawn'); + // @ts-expect-error We know that spawnCommand exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommand('foo', ['bar'], { verbose: true }); + // @ts-expect-error TypeScript doesn't like the args type for .calledWith + assert.ok(spawnSpy.calledWith('foo', ['bar'], { verbose: true })); + }); + }); + }); + + describe('#spawn() calls execa()', () => { + describe('only the command is required', () => { + describe('no args and no options are given', () => { + it('calls execaSync with the command, args, {stdio: "inherit", cwd: this.destinationRoot()}', () => { + // @ts-expect-error We know that spawn exists on the generator. It is added with applyMixins(). + testGenerator.spawn('foo'); + expect(execa.execa).toHaveBeenCalledWith('foo', undefined, { + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), + stdio: 'inherit', + }); + }); }); }); - it('pass options', async function () { - await spawn.spawnCommand('foo', undefined, { foo: 1 }); - expect(execa.execa).toHaveBeenCalledWith('foo', undefined, { - cwd, - foo: 1, + it('passes any args and opts along to execa()', () => { + // @ts-expect-error We know that spawn exists on the generator. It is added with applyMixins(). + testGenerator.spawn('foo', ['arg1', 2, 'the third arg'], { verbose: true }); + expect(execa.execa).toHaveBeenCalledWith('foo', ['arg1', 2, 'the third arg'], { + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), stdio: 'inherit', + verbose: true, }); }); - it('allow overriding default options', async function () { - await spawn.spawnCommand('foo', undefined, { stdio: 'ignore' }); + it('can override default stdio option', () => { + // @ts-expect-error We know that spawn exists on the generator. It is added with applyMixins(). + testGenerator.spawn('foo', undefined, { stdio: 'pipe' }); expect(execa.execa).toHaveBeenCalledWith('foo', undefined, { - cwd, - stdio: 'ignore', + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), + stdio: 'pipe', }); }); }); describe('#spawnCommandSync()', () => { - it('provide default options', function () { - spawn.spawnCommandSync('foo'); - expect(execa.execaCommandSync).toHaveBeenCalledWith('foo', { - cwd, - stdio: 'inherit', + describe('only the command is required', () => { + describe('no args and no options are given', () => { + it('calls execaCommandSync with the command, {stdio: "inherit", cwd: this.destinationRoot()}', () => { + // @ts-expect-error We know that spawnCommandSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommandSync('foo'); + expect(execa.execaCommandSync).toHaveBeenCalledWith('foo', { + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), + stdio: 'inherit', + }); + }); }); }); - it('pass arguments', function () { - spawn.spawnCommandSync('foo', ['bar']); - expect(execa.execaSync).toHaveBeenCalledWith('foo', ['bar'], { - cwd, - stdio: 'inherit', + describe('calls spawnSync if args and/or opts are given', () => { + it('args given are passed to spawnSync', () => { + // @ts-expect-error We know that spawnSync exists on the generator. It is added with applyMixins(). + const spawnSyncSpy = spy(testGenerator, 'spawnSync'); + // @ts-expect-error We know that spawnCommandSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommandSync('foo', ['bar']); + // @ts-expect-error TypeScript doesn't like the args type for .calledWith + assert.ok(spawnSyncSpy.calledWith('foo', ['bar'], undefined)); + }); + it('opts given are passed to spawnSync', () => { + // @ts-expect-error We know that spawnSync exists on the generator. It is added with applyMixins(). + const spawnSyncSpy = spy(testGenerator, 'spawnSync'); + // @ts-expect-error We know that spawnCommandSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommandSync('foo', undefined, { verbose: true }); + // @ts-expect-error TypeScript doesn't like the args type for .calledWith + assert.ok(spawnSyncSpy.calledWith('foo', undefined, { verbose: true })); + }); + it('both args and opts given are passed to spawnSync', () => { + // @ts-expect-error We know that spawnSync exists on the generator. It is added with applyMixins(). + const spawnSyncSpy = spy(testGenerator, 'spawnSync'); + // @ts-expect-error We know that spawnCommandSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnCommandSync('foo', ['bar'], { verbose: true }); + // @ts-expect-error TypeScript doesn't like the args type for .calledWith + assert.ok(spawnSyncSpy.calledWith('foo', ['bar'], { verbose: true })); }); }); + }); - it('pass options', function () { - spawn.spawnCommandSync('foo', undefined, { foo: 1 }); - expect(execa.execaSync).toHaveBeenCalledWith('foo', undefined, { - cwd, - foo: 1, + describe('#spawnSync() calls execaSync', () => { + describe('only the command is required', () => { + describe('no args and no options are given', () => { + it('calls execaSync with the command, args, {stdio: "inherit", cwd: this.destinationRoot()}', () => { + // @ts-expect-error We know that spawnSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnSync('foo'); + expect(execa.execaSync).toHaveBeenCalledWith('foo', undefined, { + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), + stdio: 'inherit', + }); + }); + }); + }); + + it('passes any args and opts along to execaSync()', () => { + // @ts-expect-error We know that spawnSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnSync('foo', ['arg1', 2, 'the third arg'], { verbose: true }); + expect(execa.execaSync).toHaveBeenCalledWith('foo', ['arg1', 2, 'the third arg'], { + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), stdio: 'inherit', + verbose: true, }); }); - it('allow overriding default options', function () { - spawn.spawnCommandSync('foo', undefined, { stdio: 'pipe' }); + it('can override default stdio option', () => { + // @ts-expect-error We know that spawnSync exists on the generator. It is added with applyMixins(). + testGenerator.spawnSync('foo', undefined, { stdio: 'pipe' }); expect(execa.execaSync).toHaveBeenCalledWith('foo', undefined, { - cwd, + // @ts-expect-error We know that destinationRoot() exists for the generator. + cwd: testGenerator.destinationRoot(), stdio: 'pipe', }); });