import { DbTransaction } from '@/application/contracts' import { Controller } from '@/application/controllers' import { {{ className }} } from '@/application/decorators' import { mock, MockProxy } from 'jest-mock-extended' describe('{{ className }}', () => { let db: MockProxy let decoratee: MockProxy let sut: {{ className }} beforeAll(() => { db = mock() decoratee = mock() decoratee.perform.mockResolvedValue({ statusCode: 204, data: null }) decoratee.buildValidators.mockResolvedValue([] as unknown as Validator[]) }) beforeEach(() => { sut = new {{ className }}(decoratee, db) }) it('should extend Controller', async () => { expect(sut).toBeInstanceOf(Controller) }) it('should call buildValidators', async () => { sut.buildValidators({ tenant: 'a' }) expect(decoratee.buildValidators).toHaveBeenCalledWith({ tenant: 'a' }) expect(decoratee.buildValidators).toHaveBeenCalledTimes(1) }) it('should open transaction', async () => { await sut.perform({ any: 'any' }) expect(db.openTransaction).toHaveBeenCalledWith() expect(db.openTransaction).toHaveBeenCalledTimes(1) }) it('should execute decoratee', async () => { await sut.perform({ any: 'any' }) expect(decoratee.perform).toHaveBeenCalledWith({ any: 'any' }) expect(decoratee.perform).toHaveBeenCalledTimes(1) }) it('should call commit and close transaction on success', async () => { await sut.perform({ any: 'any' }) expect(db.commit).toHaveBeenCalledWith() expect(db.commit).toHaveBeenCalledTimes(1) expect(db.rollback).not.toHaveBeenCalled() expect(db.closeTransaction).toHaveBeenCalledWith() expect(db.closeTransaction).toHaveBeenCalledTimes(1) }) it('should call rollback and close transaction on failure', async () => { decoratee.perform.mockRejectedValueOnce(new Error('decoratee_error')) sut.perform({ any: 'any' }).catch(() => { expect(db.commit).not.toHaveBeenCalled() expect(db.rollback).toHaveBeenCalledWith() expect(db.rollback).toHaveBeenCalledTimes(1) expect(db.closeTransaction).toHaveBeenCalledWith() expect(db.closeTransaction).toHaveBeenCalledTimes(1) }) }) it('should return same result as decoratee on success', async () => { const httpResponse = await sut.perform({ any: 'any' }) expect(httpResponse).toEqual({ statusCode: 204, data: null }) }) it('should rethrow if decoratee throws', async () => { const error = new Error('decoratee_error') decoratee.perform.mockRejectedValueOnce(error) const promise = sut.perform({ any: 'any' }) await expect(promise).rejects.toThrow(error) }) })