UNPKG

@cmmv/repository

Version:

Repository module using TypeORM for CMMV

281 lines (280 loc) 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const fs = require("node:fs"); const repository_transpiler_1 = require("../lib/repository.transpiler"); const core_1 = require("@cmmv/core"); // Mock das dependências externas vitest_1.vi.mock('node:fs', () => ({ writeFileSync: vitest_1.vi.fn(), existsSync: vitest_1.vi.fn().mockReturnValue(true), mkdirSync: vitest_1.vi.fn(), appendFileSync: vitest_1.vi.fn(), })); vitest_1.vi.mock('node:path', () => ({ join: vitest_1.vi.fn((...args) => args.join('/')), resolve: vitest_1.vi.fn((...args) => args.join('/')), dirname: vitest_1.vi.fn((path) => path.split('/').slice(0, -1).join('/')), })); vitest_1.vi.mock('@cmmv/core', () => { return { AbstractTranspile: class MockAbstractTranspile { constructor() { } transpile() { return true; } getGeneratedPath() { return 'generated/path'; } getRootPath() { return 'root/path'; } getImportPath() { return '@import/path'; } getImportPathRelative() { return '../relative/path'; } getImportPathWithoutSubPath() { return '@import/path'; } removeExtraSpaces(text) { return text; } removeTelemetry(text) { return text; } }, Config: { get: vitest_1.vi.fn(), }, Scope: { getArray: vitest_1.vi.fn(), }, ITranspile: Symbol('ITranspile'), IContract: Symbol('IContract'), CONTROLLER_NAME_METADATA: Symbol('CONTROLLER_NAME_METADATA'), }; }); (0, vitest_1.describe)('RepositoryTranspile', () => { let repositoryTranspile; let mockContract; (0, vitest_1.beforeEach)(() => { vitest_1.vi.resetAllMocks(); repositoryTranspile = new repository_transpiler_1.RepositoryTranspile(); // Configurar mock de Config.get com valores padrão vitest_1.vi.mocked(core_1.Config.get).mockImplementation((key) => { if (key === 'repository.type') return 'mongodb'; if (key === 'app.telemetry') return true; if (key === 'db') return 'mongodb'; return null; }); // Criar um mock de contrato mockContract = { controllerName: 'Test', generateEntities: true, generateController: true, fields: [ { propertyKey: 'name', protoType: 'string', nullable: false, index: true, }, { propertyKey: 'age', protoType: 'int32', nullable: true, }, ], services: [ { functionName: 'customFunction', request: 'CustomRequest', response: 'CustomResponse', createBoilerplate: true, }, ], options: { databaseFakeDelete: true, databaseTimestamps: true, databaseUserAction: false, moduleContract: false, databaseSchemaName: 'test_collection', }, indexs: [ { name: 'idx_test_name_age', fields: ['name', 'age'], options: { unique: true }, }, ], }; // Configurar Reflect.getMetadata para retornar o nome do controlador Reflect.getMetadata = vitest_1.vi.fn().mockReturnValue('Test'); // Configurar Scope.getArray para retornar um array com o mock de contrato vitest_1.vi.mocked(core_1.Scope.getArray).mockReturnValue([mockContract]); }); (0, vitest_1.afterEach)(() => { vitest_1.vi.resetAllMocks(); }); (0, vitest_1.describe)('run', () => { (0, vitest_1.it)('should run the transpile process', () => { // Spy nos métodos privados const generateEntitiesSpy = vitest_1.vi.spyOn(repositoryTranspile, 'generateEntities'); const generateServicesSpy = vitest_1.vi.spyOn(repositoryTranspile, 'generateServices'); repositoryTranspile.run(); // Verificar se Scope.getArray foi chamado para obter contratos (0, vitest_1.expect)(core_1.Scope.getArray).toHaveBeenCalledWith('__contracts'); // Verificar se os métodos de geração foram chamados (0, vitest_1.expect)(generateEntitiesSpy).toHaveBeenCalledWith(mockContract); (0, vitest_1.expect)(generateServicesSpy).toHaveBeenCalledWith(mockContract); }); (0, vitest_1.it)('should not generate entities if flag is false', () => { // Modificar o contrato para não gerar entidades mockContract.generateEntities = false; const generateEntitiesSpy = vitest_1.vi.spyOn(repositoryTranspile, 'generateEntities'); const generateServicesSpy = vitest_1.vi.spyOn(repositoryTranspile, 'generateServices'); repositoryTranspile.run(); (0, vitest_1.expect)(generateEntitiesSpy).not.toHaveBeenCalled(); (0, vitest_1.expect)(generateServicesSpy).toHaveBeenCalledWith(mockContract); }); (0, vitest_1.it)('should not generate controller if flag is false', () => { // Modificar o contrato para não gerar controller mockContract.generateController = false; const generateEntitiesSpy = vitest_1.vi.spyOn(repositoryTranspile, 'generateEntities'); const generateServicesSpy = vitest_1.vi.spyOn(repositoryTranspile, 'generateServices'); repositoryTranspile.run(); (0, vitest_1.expect)(generateEntitiesSpy).toHaveBeenCalledWith(mockContract); (0, vitest_1.expect)(generateServicesSpy).not.toHaveBeenCalled(); }); }); (0, vitest_1.describe)('generateEntities', () => { (0, vitest_1.it)('should generate entity file with correct content', () => { // Chamar o método privado diretamente repositoryTranspile.generateEntities(mockContract); // Verificar se writeFileSync foi chamado (0, vitest_1.expect)(fs.writeFileSync).toHaveBeenCalled(); // Capturar os argumentos da chamada const callArgs = vitest_1.vi.mocked(fs.writeFileSync).mock.calls[0]; // Verificar o conteúdo pelo segundo parâmetro, que é a string do arquivo const fileContent = callArgs[1]; // Verificar conteúdo esperado (0, vitest_1.expect)(fileContent).toContain('@Entity("test_collection")'); (0, vitest_1.expect)(fileContent).toContain('@ObjectIdColumn()'); (0, vitest_1.expect)(fileContent).toContain('_id: ObjectId'); (0, vitest_1.expect)(fileContent).toContain('export class TestEntity implements ITest'); }); (0, vitest_1.it)('should use correct path based on moduleContract flag', () => { // Testar com moduleContract = true mockContract.options.moduleContract = true; // Espionar os métodos que geram os caminhos const getGeneratedPathSpy = vitest_1.vi .spyOn(repositoryTranspile, 'getGeneratedPath') .mockReturnValue('generated/path'); /*const getRootPathSpy = vi .spyOn(repositoryTranspile as any, 'getRootPath') .mockReturnValue('root/path');*/ repositoryTranspile.generateEntities(mockContract); // Verificar se getGeneratedPath foi chamado para contrato de módulo (0, vitest_1.expect)(getGeneratedPathSpy).toHaveBeenCalled(); //expect(getRootPathSpy).not.toHaveBeenCalled(); // Redefinir mocks vitest_1.vi.clearAllMocks(); // Testar com moduleContract = false mockContract.options.moduleContract = false; repositoryTranspile.generateEntities(mockContract); // Verificar se getRootPath foi chamado para contrato padrão //expect(getRootPathSpy).toHaveBeenCalled(); //expect(getGeneratedPathSpy).not.toHaveBeenCalled(); }); }); (0, vitest_1.describe)('generateServices', () => { (0, vitest_1.it)('should generate service file with correct content', () => { // Chamar o método privado diretamente repositoryTranspile.generateServices(mockContract); // Verificar se writeFileSync foi chamado (0, vitest_1.expect)(fs.writeFileSync).toHaveBeenCalled(); // Capturar os argumentos da chamada const callArgs = vitest_1.vi.mocked(fs.writeFileSync).mock.calls[0]; // Verificar o conteúdo pelo segundo parâmetro, que é a string do arquivo const fileContent = callArgs[1]; // Verificar conteúdo esperado (0, vitest_1.expect)(fileContent).toContain('export class TestServiceGenerated extends AbstractRepositoryService'); (0, vitest_1.expect)(fileContent).toContain('protected schema = new RepositorySchema'); (0, vitest_1.expect)(fileContent).toContain('async customFunction(payload: CustomRequest): Promise<CustomResponse>'); }); (0, vitest_1.it)('should use telemetry based on config', () => { // Spy no método removeTelemetry const removeTelemetrySpy = vitest_1.vi.spyOn(repositoryTranspile, 'removeTelemetry'); // Testar com telemetry = false vitest_1.vi.mocked(core_1.Config.get).mockImplementation((key) => { if (key === 'app.telemetry') return false; if (key === 'repository.type') return 'mongodb'; if (key === 'db') return 'mongodb'; return null; }); repositoryTranspile.generateServices(mockContract); // Verificar se removeTelemetry foi chamado quando telemetry = false (0, vitest_1.expect)(removeTelemetrySpy).toHaveBeenCalled(); }); }); (0, vitest_1.describe)('Helper methods', () => { (0, vitest_1.it)('should map proto types to TypeORM types correctly', () => { const field = { protoType: 'string', protoRepeated: false }; // Testar mapeamento de string para varchar const result = repositoryTranspile.mapToTypeORMType('string', field); (0, vitest_1.expect)(result).toBe('varchar'); // Testar mapeamento de int32 para int const result2 = repositoryTranspile.mapToTypeORMType('int32', field); (0, vitest_1.expect)(result2).toBe('int'); // Testar campo repetido para simple-array field.protoRepeated = true; const result3 = repositoryTranspile.mapToTypeORMType('string', field); (0, vitest_1.expect)(result3).toBe('simple-array'); }); (0, vitest_1.it)('should map proto types to TS types correctly', () => { const field = { protoType: 'string', protoRepeated: false }; // Testar mapeamento de string para string const result = repositoryTranspile.mapToTsType('string', field); (0, vitest_1.expect)(result).toBe('string'); // Testar mapeamento de int32 para number const result2 = repositoryTranspile.mapToTsType('int32', field); (0, vitest_1.expect)(result2).toBe('number'); // Testar campo repetido para array field.protoRepeated = true; const result3 = repositoryTranspile.mapToTsType('string', field); (0, vitest_1.expect)(result3).toBe('string[]'); }); (0, vitest_1.it)('should generate indexes correctly', () => { const fields = [ { propertyKey: 'name', index: true }, { propertyKey: 'email', unique: true }, ]; const indexes = repositoryTranspile.generateIndexes('User', fields, mockContract); (0, vitest_1.expect)(indexes).toContain('@Index("idx_user_name"'); (0, vitest_1.expect)(indexes).toContain('@Index("idx_user_email"'); (0, vitest_1.expect)(indexes).toContain('{ unique: true }'); // Verificar índice de fake delete (0, vitest_1.expect)(indexes).toContain('@Index("idx_user_deleted"'); }); (0, vitest_1.it)('should generate column options correctly', () => { const field = { propertyKey: 'name', protoType: 'string', nullable: false, defaultValue: 'Default', }; const options = repositoryTranspile.generateColumnOptions(field); (0, vitest_1.expect)(options).toContain('type: "varchar"'); (0, vitest_1.expect)(options).toContain('default: "Default"'); (0, vitest_1.expect)(options).toContain('nullable: false'); }); }); });