// These service modules pull in gRPC client-config modules that read // process.env at load time; mock them (hoisted before imports) so the spec // needs no runtime env. Each mock severs an entire import subtree and still // provides a class usable as a DI token. jest.mock('../customers/customers.service', () => ({ CustomersService: class {} })); jest.mock('../catalog/catalog.service', () => ({ CatalogService: class {} })); jest.mock('../inputs/inputs.service', () => ({ InputsService: class {} })); jest.mock('./pipeline-tables.service', () => ({ PipelineTablesService: class {} })); import { BadRequestException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { DadosferaLogger } from '@dadosfera/dadosfera-logs'; import { PlatformApiController } from './platform-api.controller'; import { PlatformApiService } from './platform-api.service'; import { PipelineTablesService } from './pipeline-tables.service'; import { ElasticsearchService } from '../../services/elasticsearch'; import { DynamoDBService } from '../../services/dynamodb'; import { CustomersService } from '../customers/customers.service'; import { CatalogService } from '../catalog/catalog.service'; import { InputsService } from '../inputs/inputs.service'; const logger = { info: jest.fn(), error: jest.fn() }; const mockUser = { customer_id: 'c1', customer_name: 'cust', user_id: 'u1' } as never; // The table routes are thin: validate the body, delegate to // PipelineTablesService (covered in pipeline-tables.service.spec.ts). describe('PlatformApiController - table routes', () => { let controller: PlatformApiController; let tables: { removeTable: jest.Mock; removeTables: jest.Mock; addTable: jest.Mock }; beforeEach(async () => { tables = { removeTable: jest.fn(), removeTables: jest.fn(), addTable: jest.fn() }; const module: TestingModule = await Test.createTestingModule({ controllers: [PlatformApiController], providers: [ { provide: PlatformApiService, useValue: {} }, { provide: ElasticsearchService, useValue: {} }, { provide: DynamoDBService, useValue: {} }, { provide: CustomersService, useValue: {} }, { provide: CatalogService, useValue: {} }, { provide: InputsService, useValue: {} }, { provide: PipelineTablesService, useValue: tables }, { provide: DadosferaLogger, useValue: { logger } }, ], }).compile(); controller = module.get(PlatformApiController); }); it('deleteTable delegates', async () => { tables.removeTable.mockResolvedValue({ name: 'pedidos', is_deleted: true }); await expect(controller.deleteTable('pid', 'iid', { table_name: 'pedidos' }, mockUser)) .resolves.toEqual({ name: 'pedidos', is_deleted: true }); expect(tables.removeTable).toHaveBeenCalledWith('pid', 'iid', 'pedidos', mockUser); }); it('deleteTables delegates', async () => { tables.removeTables.mockResolvedValue({ deleted: true }); await controller.deleteTables('pid', 'iid', { table_names: ['a', 'b'] }, mockUser); expect(tables.removeTables).toHaveBeenCalledWith('pid', 'iid', ['a', 'b'], mockUser); }); it('deleteTables rejects an empty table_names before touching anything', async () => { await expect(controller.deleteTables('pid', 'iid', { table_names: [] }, mockUser)) .rejects.toBeInstanceOf(BadRequestException); expect(tables.removeTables).not.toHaveBeenCalled(); }); it('addTable delegates', async () => { const body = { table_name: 'orders', table_schema: 'public', primary_keys: ['id'], destinations: { raw: { table_schema: 'raw', table_name: 'orders' }, qualify: { table_schema: 'qualify', table_name: 'orders' }, }, }; tables.addTable.mockResolvedValue({ job_ids: ['p_2'], skipped: [] }); await expect(controller.addTable('pid', 'iid', body, mockUser)).resolves.toEqual({ job_ids: ['p_2'], skipped: [] }); expect(tables.addTable).toHaveBeenCalledWith('pid', 'iid', body, mockUser); }); });