From cd2b8a93bbf45ef5f5cd6d113e5851b7e0b717f7 Mon Sep 17 00:00:00 2001 From: Arthur Lefebvre Date: Fri, 23 Jan 2026 22:10:10 +0100 Subject: [PATCH] Author books API: use a single query with result and count --- front/src/SearchBook.vue | 2 -- front/src/api.js | 4 --- internal/apitest/get_book_per_author.go | 28 +++++++++++++------- internal/apitest/get_count_user_book_test.go | 19 ------------- internal/routes/authorbooksget.go | 24 +++-------------- internal/setup/setup.go | 3 --- 6 files changed, 21 insertions(+), 59 deletions(-) diff --git a/front/src/SearchBook.vue b/front/src/SearchBook.vue index b80868a..4cf5fc6 100644 --- a/front/src/SearchBook.vue +++ b/front/src/SearchBook.vue @@ -17,7 +17,6 @@ let data = ref(null); let error = ref(null); - let errorFetchTotal = ref(null); const pageTotal = computed(() => { let countValue = (data.value !== null) ? data.value['count'] : 0; @@ -33,7 +32,6 @@ getSearchBooks(data, error, searchTerm, lang, limit, offset.value); } else if (authorId != null) { getAuthorBooks(data, error, authorId, limit, offset.value); - getCountAuthorBooks(totalBooksData, errorFetchTotal, searchTerm); } } diff --git a/front/src/api.js b/front/src/api.js index 80ca4d0..43dbfe4 100644 --- a/front/src/api.js +++ b/front/src/api.js @@ -51,10 +51,6 @@ export function getAuthorBooks(data, error, id, limit, offset) { return useFetch(data, error, baseUrl + '/author/' + id + "/books" + "?" + queryParams.toString()); } -export function getCountAuthorBooks(data, error, id) { - return useFetch(data, error, baseUrl + '/author/' + id + "/books" + '/count'); -} - export function getBook(data, error, id) { return useFetch(data, error, baseUrl + '/book/' + id); } diff --git a/internal/apitest/get_book_per_author.go b/internal/apitest/get_book_per_author.go index 9cff7e7..3d7be68 100644 --- a/internal/apitest/get_book_per_author.go +++ b/internal/apitest/get_book_per_author.go @@ -12,6 +12,11 @@ import ( "github.com/stretchr/testify/assert" ) +type bookAuthorGetResult struct { + Count int64 `json:"count"` + Books []bookAuthorGet `json:"books"` +} + type bookAuthorGet struct { Id uint `json:"id"` Title string `json:"title" binding:"required,max=300"` @@ -22,21 +27,24 @@ type bookAuthorGet struct { } func TestSearchBookPerAuthor_Ok(t *testing.T) { - books := testFetchBookAuthor(t, 1, "", "") - assert.Equal(t, 3, len(books)) + result := testFetchBookAuthor(t, 1, "", "") + assert.Equal(t, 3, len(result.Books)) + assert.Equal(t, int64(3), result.Count) } func TestSearchBookPerAuthor_Limit(t *testing.T) { - books := testFetchBookAuthor(t, 1, "2", "") - assert.Equal(t, 2, len(books)) + result := testFetchBookAuthor(t, 1, "2", "") + assert.Equal(t, 2, len(result.Books)) + assert.Equal(t, int64(2), result.Count) } func TestSearchBookPerAuthor_Offset(t *testing.T) { - books := testFetchBookAuthor(t, 1, "10", "2") - assert.Equal(t, 1, len(books)) + result := testFetchBookAuthor(t, 1, "10", "2") + assert.Equal(t, 1, len(result.Books)) + assert.Equal(t, int64(1), result.Count) } -func testFetchBookAuthor(t *testing.T, authorId uint, limit string, offset string) []bookAuthorGet { +func testFetchBookAuthor(t *testing.T, authorId uint, limit string, offset string) bookAuthorGetResult { router := testutils.TestSetup() u, err := url.Parse(fmt.Sprintf("/author/%d/books", authorId)) @@ -60,12 +68,12 @@ func testFetchBookAuthor(t *testing.T, authorId uint, limit string, offset strin w := httptest.NewRecorder() router.ServeHTTP(w, req) - var books []bookAuthorGet + var result bookAuthorGetResult s := w.Body.String() - err = json.Unmarshal([]byte(s), &books) + err = json.Unmarshal([]byte(s), &result) if err != nil { t.Error(err) } assert.Equal(t, 200, w.Code) - return books + return result } diff --git a/internal/apitest/get_count_user_book_test.go b/internal/apitest/get_count_user_book_test.go index 30969d3..d12ceaf 100644 --- a/internal/apitest/get_count_user_book_test.go +++ b/internal/apitest/get_count_user_book_test.go @@ -71,22 +71,3 @@ func TestGetReadingBooksCountHandler_Demo(t *testing.T) { } assert.Equal(t, 2, c.Count) } - -func TestGetAuthorsBooksCountHandler_Demo(t *testing.T) { - router := testutils.TestSetup() - - token := testutils.ConnectDemoUser(router) - - req, _ := http.NewRequest("GET", "/author/1/books/count", nil) - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) - - w := httptest.NewRecorder() - router.ServeHTTP(w, req) - - var c countResponse - err := json.Unmarshal(w.Body.Bytes(), &c) - if err != nil { - t.Error(err) - } - assert.Equal(t, 3, c.Count) -} diff --git a/internal/routes/authorbooksget.go b/internal/routes/authorbooksget.go index 1e091e8..284eccd 100644 --- a/internal/routes/authorbooksget.go +++ b/internal/routes/authorbooksget.go @@ -5,6 +5,7 @@ import ( "strconv" "git.artlef.fr/PersonalLibraryManager/internal/appcontext" + "git.artlef.fr/PersonalLibraryManager/internal/dto" "git.artlef.fr/PersonalLibraryManager/internal/model" "git.artlef.fr/PersonalLibraryManager/internal/myvalidator" "git.artlef.fr/PersonalLibraryManager/internal/query" @@ -44,30 +45,11 @@ func GetAuthorBooksHandler(ac appcontext.AppContext) { myvalidator.ReturnErrorsAsJsonResponse(&ac, err) return } - ac.C.JSON(http.StatusOK, books) -} - -func GetAuthorBooksCountHandler(ac appcontext.AppContext) { - authorId, err := strconv.ParseUint(ac.C.Param("id"), 10, 64) - if err != nil { - ac.C.JSON(http.StatusBadRequest, gin.H{"error": err}) - return - } - err = myvalidator.ValidateId(ac.Db, uint(authorId), &model.Author{}) - if err != nil { - myvalidator.ReturnErrorsAsJsonResponse(&ac, err) - return - } - - user, fetchUserErr := ac.GetAuthenticatedUser() - if fetchUserErr != nil { - myvalidator.ReturnErrorsAsJsonResponse(&ac, fetchUserErr) - return - } count, err := query.FetchBookSearchByAuthorGetCount(ac.Db, user.ID, authorId) if err != nil { myvalidator.ReturnErrorsAsJsonResponse(&ac, err) return } - ac.C.JSON(http.StatusOK, gin.H{"count": count}) + ac.C.JSON(http.StatusOK, dto.BookSearchGet{Books: books, Count: count}) } + diff --git a/internal/setup/setup.go b/internal/setup/setup.go index 03ae8cf..7212c72 100644 --- a/internal/setup/setup.go +++ b/internal/setup/setup.go @@ -72,9 +72,6 @@ func Setup(config *config.Config) *gin.Engine { r.GET("/author/:id/books", func(c *gin.Context) { routes.GetAuthorBooksHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config}) }) - r.GET("/author/:id/books/count", func(c *gin.Context) { - routes.GetAuthorBooksCountHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config}) - }) r.POST("/auth/signup", func(c *gin.Context) { routes.PostSignupHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config}) })