diff --git a/packages/cli/__tests__/cli.test.ts b/packages/cli/__tests__/cli.test.ts index 83fc8ac0b..46e64f65f 100644 --- a/packages/cli/__tests__/cli.test.ts +++ b/packages/cli/__tests__/cli.test.ts @@ -1,3 +1,6 @@ +jest.mock('@constructive-io/graphql-codegen/cli/commands/generate', () => ({ + generateCommand: async () => ({ success: true, message: 'ok' }) +})); import { Inquirerer, Question } from 'inquirerer'; import { KEY_SEQUENCES, setupTests, TestEnvironment } from '../test-utils'; diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 43addb2d4..5283d2060 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -1,13 +1,13 @@ import type { ParsedArgs } from 'minimist' import codegenCommand from '../src/commands/codegen' -jest.mock('child_process', () => ({ - spawnSync: jest.fn(() => ({ status: 0 })) +const generateMock = jest.fn(async (_opts?: any) => ({ success: true, message: 'ok' })) +jest.mock('@constructive-io/graphql-codegen/cli/commands/generate', () => ({ + generateCommand: (opts: any) => generateMock(opts) })) describe('codegen command', () => { beforeEach(() => { - process.env.CONSTRUCTIVE_CODEGEN_BIN = '/fake/bin/graphql-codegen.js' jest.clearAllMocks() }) @@ -26,9 +26,7 @@ describe('codegen command', () => { spyExit.mockRestore() }) - it('invokes graphql-codegen CLI with endpoint, out, auth, and flags', async () => { - const child = require('child_process') - + it('passes endpoint, out, auth, and flags to generateCommand', async () => { const argv: Partial = { endpoint: 'http://localhost:3000/graphql', auth: 'Bearer testtoken', @@ -39,19 +37,16 @@ describe('codegen command', () => { await codegenCommand(argv, {} as any, {} as any) - expect(child.spawnSync).toHaveBeenCalled() - const args = (child.spawnSync as jest.Mock).mock.calls[0][1] as string[] - expect(args).toEqual(expect.arrayContaining(['generate'])) - expect(args).toEqual(expect.arrayContaining(['-e', 'http://localhost:3000/graphql'])) - expect(args).toEqual(expect.arrayContaining(['-o', 'graphql/codegen/dist'])) - expect(args).toEqual(expect.arrayContaining(['-a', 'Bearer testtoken'])) - expect(args).toEqual(expect.arrayContaining(['--dry-run'])) - expect(args).toEqual(expect.arrayContaining(['-v'])) + expect(generateMock).toHaveBeenCalled() + const opts = (generateMock as jest.Mock).mock.calls[0][0] + expect(opts.endpoint).toBe('http://localhost:3000/graphql') + expect(opts.output).toBe('graphql/codegen/dist') + expect(opts.authorization).toBe('Bearer testtoken') + expect(opts.verbose).toBe(true) + expect(opts.dryRun).toBe(true) }) - it('passes config path and out directory through to CLI', async () => { - const child = require('child_process') - + it('passes config path and out directory to generateCommand', async () => { const argv: Partial = { config: '/tmp/codegen.json', out: 'graphql/codegen/dist' @@ -59,14 +54,20 @@ describe('codegen command', () => { await codegenCommand(argv, {} as any, {} as any) - const args = (child.spawnSync as jest.Mock).mock.calls[0][1] as string[] - expect(args).toEqual(expect.arrayContaining(['-c', '/tmp/codegen.json'])) - expect(args).toEqual(expect.arrayContaining(['-o', 'graphql/codegen/dist'])) + const opts = (generateMock as jest.Mock).mock.calls[0][0] + expect(opts.config).toBe('/tmp/codegen.json') + expect(opts.output).toBe('graphql/codegen/dist') + }) + + it('does not depend on process.env.CONSTRUCTIVE_CODEGEN_BIN', async () => { + delete process.env.CONSTRUCTIVE_CODEGEN_BIN + const argv: Partial = { out: 'graphql/codegen/dist' } + await codegenCommand(argv, {} as any, {} as any) + expect(generateMock).toHaveBeenCalled() }) - it('exits with non-zero when underlying CLI fails', async () => { - const child = require('child_process'); - (child.spawnSync as jest.Mock).mockReturnValueOnce({ status: 1 }) + it('exits with non-zero when generateCommand fails', async () => { + generateMock.mockResolvedValueOnce({ success: false, message: 'fail', errors: ['e1'] } as any) const spyExit = jest.spyOn(process, 'exit').mockImplementation(((code?: number) => { throw new Error('exit:' + code) }) as any) const argv: Partial = { diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 1a5682add..57dca3e18 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,7 +1,6 @@ import { CLIOptions, Inquirerer } from 'inquirerer' import { ParsedArgs } from 'minimist' -import { spawnSync } from 'child_process' -import { join } from 'path' +import { generateCommand } from '@constructive-io/graphql-codegen/cli/commands/generate' const usage = ` Constructive GraphQL Codegen: @@ -28,24 +27,24 @@ export default async ( process.exit(0) } - const cwd = (argv.cwd as string) || process.cwd() const endpoint = (argv.endpoint as string) || '' - const outDir = (argv.out as string) || 'graphql/codegen/dist' + const outDir = (argv.out as string) || 'codegen' const auth = (argv.auth as string) || '' const configPath = (argv.config as string) || '' const dryRun = !!(argv['dry-run'] || argv.dryRun) const verbose = !!(argv.verbose || argv.v) - const envBin = process.env.CONSTRUCTIVE_CODEGEN_BIN - const bin = envBin || require.resolve('@constructive-io/graphql-codegen/bin/graphql-codegen.js') - const args: string[] = ['generate'] - if (configPath) args.push('-c', configPath) - if (endpoint) args.push('-e', endpoint) - if (outDir) args.push('-o', outDir) - if (auth) args.push('-a', auth) - if (dryRun) args.push('--dry-run') - if (verbose) args.push('-v') - - const res = spawnSync(process.execPath, [bin, ...args], { cwd, stdio: 'inherit' }) - if ((res.status ?? 0) !== 0) process.exit(res.status ?? 1) + const result = await generateCommand({ + config: configPath, + endpoint, + output: outDir, + authorization: auth, + verbose, + dryRun, + }) + if (!result.success) { + console.error('x', result.message) + process.exit(1) + } + console.log('[ok]', result.message) }