UNPKG

wgc

Version:

The official CLI tool to manage the GraphQL Federation Platform Cosmo

165 lines 8.54 kB
import { rmSync, mkdirSync, existsSync, writeFileSync, rmdirSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { tmpdir } from 'node:os'; import { fileURLToPath } from 'node:url'; import { Command } from 'commander'; import { describe, test, expect } from 'vitest'; import { createClient, createRouterTransport } from '@connectrpc/connect'; import { PlatformService } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb'; import { dirname } from 'pathe'; import GenerateCommand from '../src/commands/grpc-service/commands/generate.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); export const mockPlatformTransport = () => createRouterTransport(({ service }) => { service(PlatformService, {}); }); describe('gRPC Generate Command', () => { test('should generate proto and mapping files', async (testContext) => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); const tmpDir = join(tmpdir(), `grpc-test-${Date.now()}`); mkdirSync(tmpDir, { recursive: true }); testContext.onTestFinished(() => { rmdirSync(tmpDir, { recursive: true }); }); const schemaPath = resolve(__dirname, 'fixtures', 'full-schema.graphql'); await program.parseAsync(['generate', 'testservice', '-i', schemaPath, '-o', tmpDir], { from: 'user', }); // Verify the output files exist expect(existsSync(join(tmpDir, 'mapping.json'))).toBe(true); expect(existsSync(join(tmpDir, 'service.proto'))).toBe(true); expect(existsSync(join(tmpDir, 'service.proto.lock.json'))).toBe(true); }); test('should create output directory if it does not exist', async () => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); const nonExistentDir = join(tmpdir(), `grpc-test-non-existent-${Date.now()}`); // Ensure the directory doesn't exist if (existsSync(nonExistentDir)) { rmSync(nonExistentDir, { recursive: true, force: true }); } const schemaPath = resolve(__dirname, 'fixtures', 'full-schema.graphql'); await program.parseAsync(['generate', 'testservice', '-i', schemaPath, '-o', nonExistentDir], { from: 'user', }); // Verify the output directory and files exist expect(existsSync(nonExistentDir)).toBe(true); expect(existsSync(join(nonExistentDir, 'mapping.json'))).toBe(true); expect(existsSync(join(nonExistentDir, 'service.proto'))).toBe(true); expect(existsSync(join(nonExistentDir, 'service.proto.lock.json'))).toBe(true); // Cleanup rmSync(nonExistentDir, { recursive: true, force: true }); }); test('should fail when input file does not exist', async (testContext) => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); const tmpDir = join(tmpdir(), `grpc-test-${Date.now()}`); mkdirSync(tmpDir, { recursive: true }); testContext.onTestFinished(() => { rmdirSync(tmpDir, { recursive: true }); }); const nonExistentFile = join(tmpdir(), 'non-existent-schema.graphql'); await expect(program.parseAsync(['generate', 'testservice', '-i', nonExistentFile, '-o', tmpDir], { from: 'user', })).rejects.toThrow(); }); test('should fail when output path is a file', async (testContext) => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); const tmpDir = join(tmpdir(), `grpc-test-${Date.now()}`); mkdirSync(tmpDir, { recursive: true }); testContext.onTestFinished(() => { rmdirSync(tmpDir, { recursive: true }); }); const outputFile = join(tmpDir, 'output.txt'); writeFileSync(outputFile, 'test'); program.exitOverride((err) => { expect(err.message).toContain(`Output directory ${outputFile} is not a directory`); }); await expect(program.parseAsync(['generate', 'testservice', '-i', 'test/fixtures/full-schema.graphql', '-o', outputFile], { from: 'user', })).rejects.toThrow('process.exit unexpectedly called with "1"'); }); test('should generate all files with warnings', async (testContext) => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); const tmpDir = join(tmpdir(), `grpc-test-${Date.now()}`); mkdirSync(tmpDir, { recursive: true }); testContext.onTestFinished(() => { rmdirSync(tmpDir, { recursive: true }); }); const schemaPath = resolve(__dirname, 'fixtures', 'schema-with-nullable-list-items.graphql'); // Should complete successfully despite warnings await program.parseAsync(['generate', 'testservice', '-i', schemaPath, '-o', tmpDir], { from: 'user', }); // Verify the output files exist (generation should continue with warnings) expect(existsSync(join(tmpDir, 'mapping.json'))).toBe(true); expect(existsSync(join(tmpDir, 'service.proto'))).toBe(true); expect(existsSync(join(tmpDir, 'service.proto.lock.json'))).toBe(true); }); test('should fail when schema has validation errors', async (testContext) => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); program.exitOverride((err) => { expect(err.message).toContain('Schema validation failed'); }); const tmpDir = join(tmpdir(), `grpc-test-${Date.now()}`); mkdirSync(tmpDir, { recursive: true }); testContext.onTestFinished(() => { rmdirSync(tmpDir, { recursive: true }); }); const schemaPath = resolve(__dirname, 'fixtures', 'schema-with-validation-errors.graphql'); // Should fail due to validation errors await expect(program.parseAsync(['generate', 'testservice', '-i', schemaPath, '-o', tmpDir], { from: 'user', })).rejects.toThrow('process.exit unexpectedly called with "1"'); // Verify no output files were created (generation should stop on errors) expect(existsSync(join(tmpDir, 'mapping.json'))).toBe(false); expect(existsSync(join(tmpDir, 'service.proto'))).toBe(false); expect(existsSync(join(tmpDir, 'service.proto.lock.json'))).toBe(false); }); test('should display warnings and stop on errors', async (testContext) => { const client = { platform: createClient(PlatformService, mockPlatformTransport()), }; const program = new Command(); program.addCommand(GenerateCommand({ client })); program.exitOverride((err) => { expect(err.message).toContain('Schema validation failed'); }); const tmpDir = join(tmpdir(), `grpc-test-${Date.now()}`); mkdirSync(tmpDir, { recursive: true }); testContext.onTestFinished(() => { rmdirSync(tmpDir, { recursive: true }); }); const schemaPath = resolve(__dirname, 'fixtures', 'schema-with-warnings-and-errors.graphql'); // Should fail due to validation errors (despite having warnings) await expect(program.parseAsync(['generate', 'testservice', '-i', schemaPath, '-o', tmpDir], { from: 'user', })).rejects.toThrow('process.exit unexpectedly called with "1"'); // Verify no output files were created (generation should stop on errors) expect(existsSync(join(tmpDir, 'mapping.json'))).toBe(false); expect(existsSync(join(tmpDir, 'service.proto'))).toBe(false); expect(existsSync(join(tmpDir, 'service.proto.lock.json'))).toBe(false); }); }); //# sourceMappingURL=grpc-service.test.js.map