From 0c354ba3054a054456f3ae531e7f8920e3c1ffd9 Mon Sep 17 00:00:00 2001 From: Ivo Pereira Date: Sat, 1 Oct 2022 01:14:27 +0000 Subject: [PATCH 1/4] implement book suggestion model --- domain/entity/bookSuggestion.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 domain/entity/bookSuggestion.ts diff --git a/domain/entity/bookSuggestion.ts b/domain/entity/bookSuggestion.ts new file mode 100644 index 0000000..744728c --- /dev/null +++ b/domain/entity/bookSuggestion.ts @@ -0,0 +1,18 @@ +export default class BookSuggestion { + private readonly title: string; + + private readonly link: string; + + constructor({ title, link }: { title: string; link: string }) { + this.title = title; + this.link = link; + } + + getTitle(): string { + return this.title; + } + + getLink(): string { + return this.link; + } +} From e6f575a73f0a9b88ea0e935854157477de7a858d Mon Sep 17 00:00:00 2001 From: Ivo Pereira Date: Sat, 1 Oct 2022 01:14:58 +0000 Subject: [PATCH 2/4] implement use case to save book suggestion --- .../saveBookSuggestionForBookClubUseCase.ts | 35 +++++++++++++++++++ ...veBookSuggestionForBookClubUseCaseInput.ts | 5 +++ 2 files changed, 40 insertions(+) create mode 100644 application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCase.ts create mode 100644 application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCaseInput.ts diff --git a/application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCase.ts b/application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCase.ts new file mode 100644 index 0000000..b486b53 --- /dev/null +++ b/application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCase.ts @@ -0,0 +1,35 @@ +import ChatService from "../../../domain/service/chatService"; +import SaveBookSuggestionForBookClubUseCaseInput from "./saveBookSuggestionForBookClubUseCaseInput"; +import BookSuggestionsRepository from "../../../domain/repository/bookSuggestionsRepository"; +import BookSuggestion from "../../../domain/entity/bookSuggestion"; + +export default class SaveBookSuggestionForBookClubUseCase { + private bookSuggestionsRepository: BookSuggestionsRepository; + + private chatService: ChatService; + + constructor({ + chatService, + bookSuggestionsRepository, + }: { + chatService: ChatService; + bookSuggestionsRepository: BookSuggestionsRepository; + }) { + this.chatService = chatService; + this.bookSuggestionsRepository = bookSuggestionsRepository; + } + + async execute({ title, link, channelId }: SaveBookSuggestionForBookClubUseCaseInput): Promise { + const bookSuggestionAlreadyExists = this.bookSuggestionsRepository.findByTitle(title); + if (bookSuggestionAlreadyExists) { + this.chatService.sendMessageToChannel( + `Infelizmente o conteúdo **"${title}"** já tinha sido sugerido.`, + channelId + ); + return; + } + + this.bookSuggestionsRepository.add(new BookSuggestion({ title, link })); + this.chatService.sendMessageToChannel(`A sugestão **"${title}"** foi enviada.`, channelId); + } +} diff --git a/application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCaseInput.ts b/application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCaseInput.ts new file mode 100644 index 0000000..1fa31fa --- /dev/null +++ b/application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCaseInput.ts @@ -0,0 +1,5 @@ +export default interface SaveBookSuggestionForBookClubUseCaseInput { + title: string; + link: string; + channelId: string; +} From 7d540099e81d5bdd603ac8982a138ed656929bed Mon Sep 17 00:00:00 2001 From: Ivo Pereira Date: Sat, 1 Oct 2022 01:15:21 +0000 Subject: [PATCH 3/4] define book suggestions repository interface --- domain/repository/bookSuggestionsRepository.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 domain/repository/bookSuggestionsRepository.ts diff --git a/domain/repository/bookSuggestionsRepository.ts b/domain/repository/bookSuggestionsRepository.ts new file mode 100644 index 0000000..1fddfa0 --- /dev/null +++ b/domain/repository/bookSuggestionsRepository.ts @@ -0,0 +1,6 @@ +import BookSuggestion from "../entity/bookSuggestion"; + +export default interface BookSuggestionsRepository { + add(bookSuggestion: BookSuggestion): void; + findByTitle(title: string): BookSuggestion | null; +} From 0531f9eb79f28b601986bd20a1f5cfab6a176107 Mon Sep 17 00:00:00 2001 From: Ivo Pereira Date: Sat, 1 Oct 2022 01:15:34 +0000 Subject: [PATCH 4/4] add tests --- ...veBookSuggestionForBookClubUseCase.spec.ts | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 vitest/application/usecases/saveBookSuggestionForBookClubUseCase.spec.ts diff --git a/vitest/application/usecases/saveBookSuggestionForBookClubUseCase.spec.ts b/vitest/application/usecases/saveBookSuggestionForBookClubUseCase.spec.ts new file mode 100644 index 0000000..9b0fc8f --- /dev/null +++ b/vitest/application/usecases/saveBookSuggestionForBookClubUseCase.spec.ts @@ -0,0 +1,87 @@ +import { vi, describe, it, expect } from "vitest"; +import SaveBookSuggestionForBookClubUseCase from "../../../application/usecases/saveBookSuggestionForBookClubUseCase/saveBookSuggestionForBookClubUseCase"; +import BookSuggestion from "../../../domain/entity/bookSuggestion"; + +describe("send book suggestion for book club use case", () => { + it("should save in book suggestions repository the suggested book", async () => { + const bookSuggestionsRepository = { + add: vi.fn(), + findByTitle: vi.fn(), + }; + + const chatService = { + sendMessageToChannel: vi.fn(), + }; + + await new SaveBookSuggestionForBookClubUseCase({ + bookSuggestionsRepository, + chatService, + }).execute({ + title: "The Lord of the Rings", + link: "https://www.amazon.com/Lord-Rings-1-3-J-R-R-Tolkien/dp/0618260307", + channelId: "855861944930402342", + }); + + expect(bookSuggestionsRepository.add).toHaveBeenCalledWith({ + title: "The Lord of the Rings", + link: "https://www.amazon.com/Lord-Rings-1-3-J-R-R-Tolkien/dp/0618260307", + }); + }); + + it("should send a message from chatService thanking the user", async () => { + const bookSuggestionsRepository = { + add: vi.fn(), + findByTitle: vi.fn(), + }; + + const chatService = { + sendMessageToChannel: vi.fn(), + }; + + const spy = vi.spyOn(chatService, "sendMessageToChannel"); + + await new SaveBookSuggestionForBookClubUseCase({ + bookSuggestionsRepository, + chatService, + }).execute({ + title: "The Lord of the Rings", + link: "https://www.amazon.com/Lord-Rings-1-3-J-R-R-Tolkien/dp/0618260307", + channelId: "855861944930402342", + }); + + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith('A sugestão **"The Lord of the Rings"** foi enviada.', "855861944930402342"); + }); + + it("should send a message from chatService in case the book was already suggested", async () => { + const bookSuggestionsRepository = { + add: vi.fn(), + findByTitle: () => + new BookSuggestion({ + title: "The Lord of the Rings", + link: "https://www.amazon.com/Lord-Rings-1-3-J-R-R-Tolkien/dp/0618260307", + }), + }; + + const chatService = { + sendMessageToChannel: vi.fn(), + }; + + const spy = vi.spyOn(chatService, "sendMessageToChannel"); + + await new SaveBookSuggestionForBookClubUseCase({ + bookSuggestionsRepository, + chatService, + }).execute({ + title: "The Lord of the Rings", + link: "https://www.amazon.com/Lord-Rings-1-3-J-R-R-Tolkien/dp/0618260307", + channelId: "855861944930402342", + }); + + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith( + 'Infelizmente o conteúdo **"The Lord of the Rings"** já tinha sido sugerido.', + "855861944930402342" + ); + }); +});