Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SD/fix/#66 fixed case sensitivity in book search #67

Merged
merged 1 commit into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ public ResponseEntity<BookDTO> getBookById(@PathVariable("id") Long id){
}

@PostMapping
public ResponseEntity<?> addBook(@Valid @RequestBody BookDTO bookDTO){
public ResponseEntity<BookDTO> addBook(@Valid @RequestBody BookDTO bookDTO){
BookDTO savedBook = bookService.addBook(bookDTO);
return ResponseEntity.created(URI.create("/api/v1/books/" + savedBook.id()))
.body(savedBook);
}

@DeleteMapping("{id}")
public ResponseEntity<?> deleteBookById(@PathVariable("id") Long id){
public ResponseEntity<BookDTO> deleteBookById(@PathVariable("id") Long id){
bookService.deleteBookById(id);
return ResponseEntity.noContent().build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ public class BookService {

private final int maxPageSize;
private final int maxQueryLength;
private final String notFoundMessage;

public BookService(BookDAO bookDAO,
@Value("${spring.search.pageable.max-page-size}") int maxPageSize,
@Value("${spring.search.max-query-length}") int maxQueryLength) {
this.bookDAO = bookDAO;
this.maxPageSize = maxPageSize;
this.maxQueryLength = maxQueryLength;
this.notFoundMessage = "Book with id [%s] not found.";
}

public Page<BookDTO> getAllBooks(Pageable pageable) {
Expand All @@ -39,7 +41,7 @@ public BookDTO getBookById(Long id){
return BookDTOMapper.INSTANCE.modelToDTO(
bookDAO.findById(id)
.orElseThrow(
() -> new ResourceNotFoundException("Book with id [%s] not found.".formatted(id))
() -> new ResourceNotFoundException(notFoundMessage.formatted(id))
));
}

Expand All @@ -62,7 +64,7 @@ public void deleteBookById(Long id) {

// check if book with id is present
if(!bookDAO.existsBookById(id)){
throw new ResourceNotFoundException("Book with id [%s] not found.".formatted(id));
throw new ResourceNotFoundException(notFoundMessage.formatted(id));
}

bookDAO.deleteBookById(id);
Expand All @@ -72,7 +74,7 @@ public BookDTO updateBook(Long id, BookDTO updateRequest) {

Book existingBook = bookDAO.findById(updateRequest.id())
.orElseThrow(() -> new ResourceNotFoundException(
"Book with id [%s] not found.".formatted(id)
notFoundMessage.formatted(id)
));


Expand Down Expand Up @@ -164,6 +166,4 @@ public Page<BookDTO> searchBooks(BookSearchRequestDTO searchRequest, Pageable pa

return bookDAO.searchBooks(query, pageable);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@
public class BookSpecifications {

public Specification<Book> hasTitleLike(String query) {
return (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.like(root.get("title"), "%" + query + "%");
return (root, criteriaQuery, criteriaBuilder) -> {
String lowercaseQuery = "%" + query.toLowerCase() + "%";
return criteriaBuilder.like(criteriaBuilder.lower(root.get("title")), lowercaseQuery);
};
}

public Specification<Book> hasAuthorNameLike(String query) {
return (root, criteriaQuery, criteriaBuilder) -> {
Join<Book, Author> join = root.join("authors");
Predicate firstNamePredicate = criteriaBuilder.like(join.get("firstName"), "%" + query + "%");
Predicate lastNamePredicate = criteriaBuilder.like(join.get("lastName"), "%" + query + "%");
String lowerCaseQuery = query.toLowerCase();

Predicate firstNamePredicate = criteriaBuilder.like(
criteriaBuilder.lower(join.get("firstName")), "%" + lowerCaseQuery + "%");
Predicate lastNamePredicate = criteriaBuilder.like(
criteriaBuilder.lower(join.get("lastName")), "%" + lowerCaseQuery + "%");

return criteriaBuilder.or(firstNamePredicate, lastNamePredicate);
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.amigoscode.cohort2d.onlinebookstore.book;

import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;

import com.amigoscode.cohort2d.onlinebookstore.author.Author;
Expand Down Expand Up @@ -49,19 +48,22 @@ public void shouldCreateTitleLikeSpecification() {

@Test
public void shouldCreateAuthorNameLikeSpecification() {
String query = "tolkien";
String query = "Tolkien";

when(root.<Book, Author>join("authors")).thenReturn(join);

Predicate mockFirstNamePredicate = mock(Predicate.class);
Predicate mockLastNamePredicate = mock(Predicate.class);
Predicate mockOrPredicate = mock(Predicate.class);

when(criteriaBuilder.like(join.get("firstName"), "%" + query + "%")).thenReturn(mockFirstNamePredicate);
when(criteriaBuilder.like(join.get("lastName"), "%" + query + "%")).thenReturn(mockLastNamePredicate);
when(criteriaBuilder.like(
criteriaBuilder.lower(
join.get("firstName")), "%" + query.toLowerCase() + "%")).thenReturn(mockFirstNamePredicate);
when(criteriaBuilder.like(
criteriaBuilder.lower(
join.get("lastName")), "%" + query.toLowerCase() + "%")).thenReturn(mockLastNamePredicate);

// TODO - fix firstName stubbing argument
when(criteriaBuilder.or(mockLastNamePredicate, mockLastNamePredicate)).thenReturn(mockOrPredicate);
doReturn(mockOrPredicate).when(criteriaBuilder).or(any(), any());

Predicate actual = underTest.hasAuthorNameLike(query).toPredicate(root, criteriaQuery, criteriaBuilder);

Expand Down