From 4d5420dab73ac15ab73f4b5b5a4ab7f5780806a3 Mon Sep 17 00:00:00 2001 From: Anthony Rey Date: Mon, 13 Nov 2023 16:49:09 +0100 Subject: [PATCH] Add isbn as parameter --- src/library/application/LibraryRoutes.tsx | 12 +++++++++--- src/library/domain/Books.ts | 3 ++- .../infrastructure/primary/BookComponent.tsx | 12 ++++++++---- src/library/infrastructure/primary/UseLoad.ts | 6 +++--- .../infrastructure/secondary/RestBooks.ts | 5 +++-- test/component/spec/library/library.spec.ts | 18 +++++++++--------- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/library/application/LibraryRoutes.tsx b/src/library/application/LibraryRoutes.tsx index 1cebe5c..1dbb45d 100644 --- a/src/library/application/LibraryRoutes.tsx +++ b/src/library/application/LibraryRoutes.tsx @@ -1,14 +1,20 @@ -import { RouteObject } from 'react-router-dom'; +import { RouteObject, useParams } from 'react-router-dom'; import { BookComponent } from '@/library/infrastructure/primary/BookComponent.tsx'; import { LibraryApp } from '@/library/application/LibraryApp.tsx'; +import { ISBN } from '@/library/domain/ISBN.ts'; + +const BooksPage = () => { + const { isbn } = useParams(); + return ; +}; export const libraryRoutes: RouteObject = { path: '/', element: , children: [ { - path: '', - element: , + path: 'book/:isbn', + element: , }, ], }; diff --git a/src/library/domain/Books.ts b/src/library/domain/Books.ts index b4a0784..196142b 100644 --- a/src/library/domain/Books.ts +++ b/src/library/domain/Books.ts @@ -1,6 +1,7 @@ import { Book } from '@/library/domain/Book'; import { Either } from '@/functional/Either'; +import { ISBN } from '@/library/domain/ISBN.ts'; export interface Books { - get(): Promise>; + get(isbn: ISBN): Promise>; } diff --git a/src/library/infrastructure/primary/BookComponent.tsx b/src/library/infrastructure/primary/BookComponent.tsx index 4c6d0ef..424aa4c 100644 --- a/src/library/infrastructure/primary/BookComponent.tsx +++ b/src/library/infrastructure/primary/BookComponent.tsx @@ -4,16 +4,20 @@ import { useTranslation } from 'react-i18next'; import { inject } from '@/injections.ts'; import { BOOKS } from '@/library/application/LibraryKeys.ts'; import { Book } from '@/library/domain/Book.ts'; +import { ISBN } from '@/library/domain/ISBN.ts'; -export const BookComponent = () => { +export const BookComponent = (props: { isbn: ISBN }) => { const books = inject(BOOKS); const { t } = useTranslation(); const [book, setBook] = useState(); - const { isInProgress, isFailing, isSuccessful, errorMessage } = useLoadEither(books.get(), book => { - setBook(book); - }); + const { isInProgress, isFailing, isSuccessful, errorMessage } = useLoadEither( + () => books.get(props.isbn), + book => { + setBook(book); + } + ); return ( <> diff --git a/src/library/infrastructure/primary/UseLoad.ts b/src/library/infrastructure/primary/UseLoad.ts index 24b591c..0cd8b3c 100644 --- a/src/library/infrastructure/primary/UseLoad.ts +++ b/src/library/infrastructure/primary/UseLoad.ts @@ -14,7 +14,7 @@ interface Loaded { isFailing: boolean; } -export const useLoadEither = (promise: Promise>, then: (value: T) => void): Loaded => { +export const useLoadEither = (promise: () => Promise>, then: (value: T) => void): Loaded => { const [errorMessage, setErrorMessage] = useState(''); const [status, setStatus] = useState(IN_PROGRESS); @@ -30,8 +30,8 @@ export const useLoadEither = (promise: Promise>, then: (valu setStatus(SUCCESS); }); - promise.then(successLoad).catch(errorLoad); - }, [promise, then]); + promise().then(successLoad).catch(errorLoad); + }, []); const is = (to: LoadingStatus): boolean => status === to; diff --git a/src/library/infrastructure/secondary/RestBooks.ts b/src/library/infrastructure/secondary/RestBooks.ts index 7ac70b9..562c0c2 100644 --- a/src/library/infrastructure/secondary/RestBooks.ts +++ b/src/library/infrastructure/secondary/RestBooks.ts @@ -3,13 +3,14 @@ import { Either } from '@/functional/Either'; import { Book } from '@/library/domain/Book'; import { AxiosInstance } from 'axios'; import { RestBook, toBook } from '@/library/infrastructure/secondary/RestBook'; +import { ISBN } from '@/library/domain/ISBN.ts'; export class RestBooks implements Books { constructor(private readonly axiosInstance: AxiosInstance) {} - get(): Promise> { + get(isbn: ISBN): Promise> { return this.axiosInstance - .get('/isbn/9780321125217.json') + .get(`/isbn/${isbn.get()}.json`) .then(response => response.data) .then(toBook) .catch(error => Promise.resolve(Either.err(error))); diff --git a/test/component/spec/library/library.spec.ts b/test/component/spec/library/library.spec.ts index f6ca60d..ea69a7a 100644 --- a/test/component/spec/library/library.spec.ts +++ b/test/component/spec/library/library.spec.ts @@ -6,7 +6,7 @@ const BOOK = { number_of_pages: 42, }; -const stubOpenLibraryIsbn = () => cy.intercept('https://openlibrary.org/isbn/9780321125217.json', BOOK); +const stubOpenLibraryIsbn = () => cy.intercept('https://openlibrary.org/isbn/9780321125217.json', BOOK).as('BOOK'); const stubOpenLibraryIsbnInvalid = () => cy.intercept('https://openlibrary.org/isbn/9780321125217.json', { @@ -34,13 +34,13 @@ describe('Library', () => { }); it('Should be loading before result', () => { - cy.visit('/', loadLanguage('en')); + cy.visit('/book/9780321125217', loadLanguage('en')); cy.contains(dataSelector('book.loading'), 'In progress'); }); it('Should be loading before result', () => { - cy.visit('/', loadLanguage('fr')); + cy.visit('/book/9780321125217', loadLanguage('fr')); cy.contains(dataSelector('book.loading'), 'En cours'); }); @@ -49,7 +49,7 @@ describe('Library', () => { it('Should not show book with network error', () => { stubOpenLibraryIsbnNetworkError(); - cy.visit('/'); + cy.visit('/book/9780321125217'); cy.contains(dataSelector('book.error'), 'Request failed'); }); @@ -57,7 +57,7 @@ describe('Library', () => { it('Should not show book with invalid ISBN', () => { stubOpenLibraryIsbnInvalid(); - cy.visit('/'); + cy.visit('/book/9780321125217'); cy.contains(dataSelector('book.error'), 'Non digits are not allowed for ISBN'); }); @@ -65,7 +65,7 @@ describe('Library', () => { it('Should get book', () => { stubOpenLibraryIsbn(); - cy.visit('/'); + cy.visit('/book/9780321125217'); cy.contains(dataSelector('book.title'), 'Domain-driven design'); cy.contains(dataSelector('book.isbn'), '9780321125217'); @@ -75,15 +75,15 @@ describe('Library', () => { it('Should have english labels', () => { stubOpenLibraryIsbn(); - cy.visit('/', loadLanguage('en')); + cy.visit('/book/9780321125217', loadLanguage('en')); cy.contains(dataSelector('book.label.title'), 'Title: '); }); - it('Should have french labels', () => { + it.only('Should have french labels', () => { stubOpenLibraryIsbn(); - cy.visit('/', loadLanguage('fr')); + cy.visit('/book/9780321125217', loadLanguage('fr')); cy.contains(dataSelector('book.label.title'), 'Titre : '); });