mirror of
https://github.com/dadosfera/maestro.git
synced 2026-09-03 21:24:49 +00:00
Review (maestro #510): batch and CDC tables are both removed through DELETE /pipeline/{id}/jobs (the platform dispatches by type: Airflow refresh vs Kafka Connect reconfigure), so the connector 'if' in the controller is gone. deleteTable/deleteTables/addTable are now thin controller methods over PipelineTablesService (mark -> resolve jobs -> platform -> rollback), with typed request bodies. Behavior change for batch: the platform refuses to remove the LAST table of a pipeline (400 'Cannot remove all jobs'), where DELETE /jobs/{id} allowed it. Co-Authored-By: WOZCODE <contact@withwoz.com>
86 lines
4.0 KiB
TypeScript
86 lines
4.0 KiB
TypeScript
// 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>(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);
|
|
});
|
|
});
|