From 017e238e3d9ab2a1fa5497325ea2e93e0c16a651 Mon Sep 17 00:00:00 2001 From: NedcloarBR Date: Sat, 17 Aug 2024 13:26:56 -0300 Subject: [PATCH] test(transaction): add unit this test file will be ignored --- .vscode/settings.json | 1 + tests/__mocks__/utils/index.ts | 1 + tests/__mocks__/utils/transactionMockInput.ts | 46 +++ tests/transaction.spec-ignore.ts | 316 ++++++++++++++++++ 4 files changed, 364 insertions(+) create mode 100644 tests/__mocks__/utils/transactionMockInput.ts create mode 100644 tests/transaction.spec-ignore.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index a2745c5..fb8baec 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "cSpell.words": [ "Adapter", "biomejs", + "cnpj", "fastify", "Fastify", "interceptors", diff --git a/tests/__mocks__/utils/index.ts b/tests/__mocks__/utils/index.ts index d909d2b..b1811d1 100644 --- a/tests/__mocks__/utils/index.ts +++ b/tests/__mocks__/utils/index.ts @@ -1,2 +1,3 @@ export * from "./formatInput"; export * from "./userMockInput"; +export * from "./transactionMockInput"; diff --git a/tests/__mocks__/utils/transactionMockInput.ts b/tests/__mocks__/utils/transactionMockInput.ts new file mode 100644 index 0000000..4439145 --- /dev/null +++ b/tests/__mocks__/utils/transactionMockInput.ts @@ -0,0 +1,46 @@ +import { $Enums } from "@prisma/client"; +import type { UserEntity } from "src/modules/user"; + +export async function transactionMockInput() { + const cpfUser1: UserEntity = { + publicId: "0a8ee1f5-1373-4767-9389-f76abf22bf4f", + money: 100, + firstName: "Miguel", + lastName: "Alexandre Uhlein1", + email: "nedcloar1_cpf1@hotmail.com", + userType: $Enums.UserType.CPF, + document: "79148189090", + }; + + const cpfUser2: UserEntity = { + publicId: "5bf57a8b-1db0-4999-868d-4d34b04f3f23", + money: 100, + firstName: "Miguel", + lastName: "Alexandre Uhlein2", + email: "nedcloar1_cpf2@hotmail.com", + userType: $Enums.UserType.CPF, + document: "98772856068", + }; + + const cnpjUser1: UserEntity = { + publicId: "d39af869-4b78-4c36-8081-123846f41b9d", + money: 100, + firstName: "Miguel", + lastName: "Alexandre Uhlein3", + email: "nedcloar1_cnpj1@hotmail.com", + userType: $Enums.UserType.CNPJ, + document: "30347915000139", + }; + + const cnpjUser2: UserEntity = { + publicId: "d39af869-4b78-4c36-8081-123846f41b9d", + money: 100, + firstName: "Miguel", + lastName: "Alexandre Uhlein4", + email: "nedcloar1_cnpj2@hotmail.com", + userType: $Enums.UserType.CNPJ, + document: "52736388000197", + }; + + return { cpfUser1, cpfUser2, cnpjUser1, cnpjUser2 }; +} diff --git a/tests/transaction.spec-ignore.ts b/tests/transaction.spec-ignore.ts new file mode 100644 index 0000000..bc092c9 --- /dev/null +++ b/tests/transaction.spec-ignore.ts @@ -0,0 +1,316 @@ +import { Test, type TestingModule } from "@nestjs/testing"; +import type { CustomPrismaService } from "nestjs-prisma"; +import { UnauthorizedError } from "src/common/errors"; +import { UserModule } from "src/modules"; +import type { ExtendedPrismaClient } from "src/modules/database/ExtendedPrismaClient"; +import { + TransactionController, + TransactionEntity, + TransactionRepository, + TransactionService, +} from "src/modules/transaction"; +import { TransactionDTO } from "src/modules/transaction/transaction.dto"; +import { UserEntity, UserRepository, UserService } from "src/modules/user"; +import { Repositories, Services } from "src/types/constants"; +import { beforeEach, describe, expect, it } from "vitest"; +import type { DeepMockProxy } from "vitest-mock-extended"; +import { mockPrismaProvider, transactionMockInput } from "./__mocks__"; + +describe("TransactionModule Tests", () => { + let transactionController: TransactionController; + let transactionService: TransactionService; + let userService: UserService; + let transactionRepository: TransactionRepository; + let prismaMock: DeepMockProxy; + + beforeEach(async () => { + const moduleRef: TestingModule = await Test.createTestingModule({ + // imports: [UserModule], + controllers: [TransactionController], + providers: [ + { + provide: Services.Transaction, + useClass: TransactionService, + }, + { + provide: Repositories.Transaction, + useClass: TransactionRepository, + }, + { + provide: Services.User, + useClass: UserService, + }, + { + provide: Repositories.User, + useClass: UserRepository, + }, + mockPrismaProvider, + ], + }).compile(); + + transactionController = moduleRef.get( + TransactionController, + ); + transactionService = moduleRef.get( + Services.Transaction, + ); + userService = moduleRef.get(Services.User); + transactionRepository = moduleRef.get( + Repositories.Transaction, + ); + prismaMock = moduleRef.get< + DeepMockProxy> + >(Services.Prisma).client; + }); + + describe("Is dependencies defined?", () => { + it("transactionController", () => { + expect(transactionController).toBeDefined(); + }); + + it("transactionService", () => { + expect(transactionService).toBeDefined(); + }); + + it("transactionRepository", () => { + expect(transactionRepository).toBeDefined(); + }); + + it("userService", () => { + expect(userService).toBeDefined(); + }); + + it("prismaMock", () => { + expect(prismaMock).toBeDefined(); + }); + }); + + it("should return the controller message", () => { + const expected = { message: "TransactionModule Controller" }; + + const result = transactionController.get(); + + expect(result).toStrictEqual(expected); + }); + + describe("/POST transaction", () => { + let cpfUser1: UserEntity; + let cpfUser2: UserEntity; + let cnpjUser1: UserEntity; + let cnpjUser2: UserEntity; + + beforeEach(async () => { + const users = await transactionMockInput(); + + cpfUser1 = users.cpfUser1; + cpfUser2 = users.cpfUser2; + cnpjUser1 = users.cnpjUser1; + cnpjUser2 = users.cnpjUser2; + }); + + it("should create a transaction from CPF to CPF user", async () => { + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 0, + password: "Mock", + }); + const sender = await userService.findByPublicId(cpfUser1.publicId); + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser2, + id: 1, + password: "Mock", + }); + const receiver = await userService.findByPublicId(cpfUser2.publicId); + + const data: TransactionDTO = { + senderDocument: sender.document, + receiverDocument: receiver.document, + value: 100, + }; + + const expected = { + id: "cd2df795-58e9-45a9-b018-31c77f74b47f", + senderId: sender.publicId, + receiverId: receiver.publicId, + timestamp: expect.any(Date), + value: 100, + }; + + prismaMock.transaction.create.mockResolvedValue({ + id: "cd2df795-58e9-45a9-b018-31c77f74b47f", + senderId: sender.publicId, + receiverId: receiver.publicId, + timestamp: new Date(), + value: 100, + }); + const transaction = await transactionController.create(data); + + expect(expected).toStrictEqual(transaction); + expect(sender.money).toBe(0); + expect(receiver.money).toBe(200); + }); + + it("should create a transaction from CPF to CNPJ user", async () => { + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 0, + password: "Mock", + }); + const sender = await userService.findByPublicId(cpfUser1.publicId); + prismaMock.user.findFirst.mockResolvedValue({ + ...cnpjUser1, + id: 1, + password: "Mock", + }); + const receiver = await userService.findByPublicId(cnpjUser1.publicId); + + const data: TransactionDTO = { + senderDocument: sender.document, + receiverDocument: receiver.document, + value: 100, + }; + + const expected = { + id: "cd2df795-58e9-45a9-b018-31c77f74b47f", + senderId: sender.publicId, + receiverId: receiver.publicId, + timestamp: expect.any(Date), + value: 100, + }; + + prismaMock.transaction.create.mockResolvedValue({ + id: "cd2df795-58e9-45a9-b018-31c77f74b47f", + senderId: sender.publicId, + receiverId: receiver.publicId, + timestamp: new Date(), + value: 100, + }); + const transaction = await transactionController.create(data); + + expect(expected).toStrictEqual(transaction); + expect(sender.money).toBe(0); + expect(receiver.money).toBe(200); + }); + + it("should not create a transaction from CNPJ to CNPJ user", async () => { + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 0, + password: "Mock", + }); + const sender = await userService.findByPublicId(cnpjUser1.publicId); + prismaMock.user.findFirst.mockResolvedValue({ + ...cnpjUser1, + id: 1, + password: "Mock", + }); + const receiver = await userService.findByPublicId(cnpjUser2.publicId); + + const data: TransactionDTO = { + senderDocument: sender.document, + receiverDocument: receiver.document, + value: 100, + }; + + try { + await transactionController.create(data); + } catch (error) { + expect(error).toBeInstanceOf(UnauthorizedError); + expect(error.message).toBe("CNPJ não pode enviar"); + } + }); + + it("should not create a transaction from CNPJ to CPF user", async () => { + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 0, + password: "Mock", + }); + const sender = await userService.findByPublicId(cnpjUser1.publicId); + prismaMock.user.findFirst.mockResolvedValue({ + ...cnpjUser1, + id: 1, + password: "Mock", + }); + const receiver = await userService.findByPublicId(cpfUser1.publicId); + + const data: TransactionDTO = { + senderDocument: sender.document, + receiverDocument: receiver.document, + value: 100, + }; + + prismaMock.transaction.create.mockRejectedValue( + new UnauthorizedError("CNPJ não pode enviar"), + ); + try { + await transactionController.create(data); + } catch (error) { + expect(error).toBeInstanceOf(UnauthorizedError); + expect(error.message).toBe("CNPJ não pode enviar"); + } + }); + + it("should not create a transaction because user don't have the specified money amount", async () => { + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 0, + password: "Mock", + }); + const sender = await userService.findByPublicId(cpfUser1.publicId); + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser2, + id: 1, + password: "Mock", + }); + const receiver = await userService.findByPublicId(cpfUser2.publicId); + + const data: TransactionDTO = { + senderDocument: sender.document, + receiverDocument: receiver.document, + value: 200, + }; + + prismaMock.transaction.create.mockRejectedValue( + new UnauthorizedError("Sender não tem dinheiro o suficiente"), + ); + try { + await transactionController.create(data); + } catch (error) { + expect(error).toBeInstanceOf(UnauthorizedError); + expect(error.message).toBe("Sender não tem dinheiro o suficiente"); + } + }); + + it("should not create a transaction because user cannot transfer to yourself", async () => { + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 0, + password: "Mock", + }); + const sender = await userService.findByPublicId(cpfUser1.publicId); + prismaMock.user.findFirst.mockResolvedValue({ + ...cpfUser1, + id: 1, + password: "Mock", + }); + const receiver = await userService.findByPublicId(cpfUser1.publicId); + + const data: TransactionDTO = { + senderDocument: sender.document, + receiverDocument: receiver.document, + value: 100, + }; + + prismaMock.transaction.create.mockRejectedValue( + new UnauthorizedError("Não é possível enviar para si mesmo"), + ); + try { + await transactionController.create(data); + } catch (error) { + expect(error).toBeInstanceOf(UnauthorizedError); + expect(error.message).toBe("Não é possível enviar para si mesmo"); + } + }); + }); +});