From 261da03f8a52e17bf2e6d12c5c6c3042dc28c760 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Fri, 5 Apr 2024 13:38:36 +0000 Subject: [PATCH 01/11] Feat: Added functions postItems, getMediaItem, and deleteMediaItem --- .../lesson16/web/MediaItemsController.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java index cae5ff06..397c67a5 100644 --- a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java @@ -4,11 +4,20 @@ import com.codedifferently.lesson16.library.Library; import com.codedifferently.lesson16.library.MediaItem; import com.codedifferently.lesson16.library.search.SearchCriteria; +import jakarta.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Set; +import java.util.UUID; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; @RestController public class MediaItemsController { @@ -27,4 +36,31 @@ public GetMediaItemsResponse getItems() { var response = GetMediaItemsResponse.builder().items(responseItems).build(); return response; } + + @PostMapping("/items") + public CreateMediaItemResponse postItem(@Valid @RequestBody CreateMediaItemRequest req) { + MediaItem media = MediaItemRequest.asMediaItem(req.getItem()); + library.addMediaItem(media, librarian); + return CreateMediaItemResponse.builder().item(MediaItemResponse.from(media)).build(); + } + + @GetMapping("/items/{id}") + public GetMediaItemsResponse getMediaItem(@PathVariable String id) { + Set items = library.search(SearchCriteria.builder().id(id).build()); + if (items.isEmpty()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Media item not found"); + } + List responseItems = items.stream().map(MediaItemResponse::from).toList(); + var response = GetMediaItemsResponse.builder().items(responseItems).build(); + return response; + } + + @DeleteMapping("/items/{id}") + public ResponseEntity deleteMediaItem(@PathVariable String id) { + if (!library.hasMediaItem(UUID.fromString(id))) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Media item not found"); + } + library.removeMediaItem(UUID.fromString(id), librarian); + return ResponseEntity.noContent().build(); + } } From 5006fd3b071bbaed54e9f64491b36955ff4423f1 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Mon, 8 Apr 2024 15:58:23 +0000 Subject: [PATCH 02/11] Feat: Added patron controllers and tests --- .../lesson16/web/CreatePatronRequest.java | 17 +++ .../lesson16/web/CreatePatronResponse.java | 10 ++ .../lesson16/web/GetPatronsResponse.java | 12 ++ .../lesson16/web/MediaItemsController.java | 14 +- .../lesson16/web/PatronRequest.java | 27 ++++ .../lesson16/web/PatronResponse.java | 25 +++ .../lesson16/web/PatronsController.java | 69 +++++++++ .../lesson16/web/PatronControllerTest.java | 143 ++++++++++++++++++ 8 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronRequest.java create mode 100644 lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronResponse.java create mode 100644 lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/GetPatronsResponse.java create mode 100644 lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronRequest.java create mode 100644 lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronResponse.java create mode 100644 lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java create mode 100644 lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronRequest.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronRequest.java new file mode 100644 index 00000000..db557148 --- /dev/null +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronRequest.java @@ -0,0 +1,17 @@ +package com.codedifferently.lesson16.web; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class CreatePatronRequest { + @NotNull(message = "patron is required") @Valid + private PatronRequest patron; +} diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronResponse.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronResponse.java new file mode 100644 index 00000000..3799bed1 --- /dev/null +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/CreatePatronResponse.java @@ -0,0 +1,10 @@ +package com.codedifferently.lesson16.web; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class CreatePatronResponse { + private PatronResponse patron; +} diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/GetPatronsResponse.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/GetPatronsResponse.java new file mode 100644 index 00000000..846639a5 --- /dev/null +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/GetPatronsResponse.java @@ -0,0 +1,12 @@ +package com.codedifferently.lesson16.web; + +import java.util.List; +import lombok.Builder; +import lombok.Data; +import lombok.Singular; + +@Data +@Builder +public class GetPatronsResponse { + @Singular private List patrons; +} diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java index 397c67a5..9c31519f 100644 --- a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java @@ -19,6 +19,10 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; +// ___________________________________________________________ +// THIS CODE WAS MADE IN COLLABORATION WITH VICENTE AND RICH +// ___________________________________________________________ + @RestController public class MediaItemsController { private final Library library; @@ -45,8 +49,8 @@ public CreateMediaItemResponse postItem(@Valid @RequestBody CreateMediaItemReque } @GetMapping("/items/{id}") - public GetMediaItemsResponse getMediaItem(@PathVariable String id) { - Set items = library.search(SearchCriteria.builder().id(id).build()); + public GetMediaItemsResponse getItem(@PathVariable UUID id) { + Set items = library.search(SearchCriteria.builder().id(id.toString()).build()); if (items.isEmpty()) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Media item not found"); } @@ -56,11 +60,11 @@ public GetMediaItemsResponse getMediaItem(@PathVariable String id) { } @DeleteMapping("/items/{id}") - public ResponseEntity deleteMediaItem(@PathVariable String id) { - if (!library.hasMediaItem(UUID.fromString(id))) { + public ResponseEntity deleteItem(@PathVariable UUID id) { + if (!library.hasMediaItem(id)) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Media item not found"); } - library.removeMediaItem(UUID.fromString(id), librarian); + library.removeMediaItem(id, librarian); return ResponseEntity.noContent().build(); } } diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronRequest.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronRequest.java new file mode 100644 index 00000000..c0f24788 --- /dev/null +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronRequest.java @@ -0,0 +1,27 @@ +package com.codedifferently.lesson16.web; + +import com.codedifferently.lesson16.library.Patron; +import jakarta.validation.constraints.NotBlank; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PatronRequest { + private UUID id; + + @NotBlank(message = "Email is required") + private String email; + + @NotBlank(message = "Name is required") + private String name; + + public static Patron asPatron(PatronRequest request) { + return new Patron(request.name, request.email); + } +} diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronResponse.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronResponse.java new file mode 100644 index 00000000..2e00587b --- /dev/null +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronResponse.java @@ -0,0 +1,25 @@ +package com.codedifferently.lesson16.web; + +import com.codedifferently.lesson16.library.LibraryGuest; +import jakarta.validation.constraints.NotBlank; +import java.util.UUID; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class PatronResponse { + private UUID id; + + @NotBlank(message = "Email is required") + private String email; + + @NotBlank(message = "Name is required") + private String name; + + public static PatronResponse from(LibraryGuest patron) { + var result = + PatronResponse.builder().id(patron.getId()).name(patron.getName()).email(patron.getEmail()); + return result.build(); + } +} diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java new file mode 100644 index 00000000..919101c9 --- /dev/null +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java @@ -0,0 +1,69 @@ +package com.codedifferently.lesson16.web; + +import com.codedifferently.lesson16.library.Library; +import com.codedifferently.lesson16.library.LibraryGuest; +import com.codedifferently.lesson16.library.Patron; +import jakarta.validation.Valid; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +@RestController +public class PatronsController { + private final Library library; + + public PatronsController(Library library) throws IOException { + this.library = library; + } + + @GetMapping("/patrons") + public GetPatronsResponse getPatrons() { + Set patrons = library.getPatrons(); + List responsePatrons = patrons.stream().map(PatronResponse::from).toList(); + var response = GetPatronsResponse.builder().patrons(responsePatrons).build(); + return response; + } + + @PostMapping("/patrons") + public CreatePatronResponse postPatron(@Valid @RequestBody CreatePatronRequest req) { + Patron guest = PatronRequest.asPatron(req.getPatron()); + library.addLibraryGuest(guest); + return CreatePatronResponse.builder().patron(PatronResponse.from(guest)).build(); + } + + @GetMapping("/patrons/{id}") + public GetPatronsResponse getPatron(@PathVariable("id") UUID id) { + if (!library.hasLibraryGuest(id)) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Guest patron not found"); + } + Set patrons = new HashSet<>(); + for (LibraryGuest guest : library.getPatrons()) { + if (guest.getId() == id) { + patrons.add(guest); + } + } + List responsePatrons = patrons.stream().map(PatronResponse::from).toList(); + var response = GetPatronsResponse.builder().patrons(responsePatrons).build(); + return response; + } + + @DeleteMapping("/patrons/{id}") + public ResponseEntity deletePatron(@PathVariable() UUID id) { + if (!library.hasLibraryGuest(id)) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Guest patron not found"); + } + library.removeLibraryGuest(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java new file mode 100644 index 00000000..bb907886 --- /dev/null +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -0,0 +1,143 @@ +package com.codedifferently.lesson16.web; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.codedifferently.lesson16.Lesson16; +import com.codedifferently.lesson16.library.Library; +import com.codedifferently.lesson16.library.LibraryGuest; +import com.codedifferently.lesson16.library.Patron; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@SpringBootTest +@ContextConfiguration(classes = Lesson16.class) +class PatronControllerTest { + private static MockMvc mockMvc; + @Autowired private Library library; + + @BeforeAll + static void setUp(WebApplicationContext wac) { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + @Test + void testController_getsAllPatrons() throws Exception { + mockMvc + .perform(get("/patrons").contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.patrons").isArray()) + .andExpect(jsonPath("$.patrons.length()").value(5)); + } + + @Test + void testController_deletesPatron() throws Exception { + Set pat = library.getPatrons(); + UUID ids = UUID.fromString("00000000-0000-0000-0000-000000000000"); + for (LibraryGuest guest : pat) { + if (guest.getName() == "Alice Johnson") { + ids = guest.getId(); + } + } + + mockMvc + .perform(delete("/patrons/" + ids.toString()).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + int i = 0; + for (LibraryGuest guest : pat) { + if (guest.getName() == "Alice Johnson") { + i++; + } + } + assertThat(i).isEqualTo(0); + } + + @Test + void testController_getsAnPatron() throws Exception { + Set pat = library.getPatrons(); + UUID ids = UUID.fromString("00000000-0000-0000-0000-000000000000"); + for (LibraryGuest guest : pat) { + if (guest.getName() == "Bob Williams") { + ids = guest.getId(); + } + } + mockMvc + .perform(get("/patrons/" + ids.toString()).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void testController_returnsNotFoundOnGetPatron() throws Exception { + mockMvc + .perform( + get("/patrons/00000000-0000-0000-0000-000000000000") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + } + + @Test + void testController_reportsBadRequestOnAddPatron() throws Exception { + String json = "{}"; + + mockMvc + .perform(post("/patrons").contentType(MediaType.APPLICATION_JSON).content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.errors").isArray()) + .andExpect(jsonPath("$.errors.length()").value(1)); + } + + @Test + void testController_addsPatron() throws Exception { + String json = + """ + { + "guests":{ + { + "id": "ca4a7abd-95fa-43db-91c7-5d80e27d821a" + "name": "John Book", + "email": "john.Book@reallibrary.org", + "checkedOutPatrons": [] + } + } + """; + + mockMvc + .perform(post("/patrons").contentType(MediaType.APPLICATION_JSON).content(json)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.patron.id").value("ca4a7abd-95fa-43db-91c7-5d80e27d821a")); + + Set patrons = new HashSet<>(); + for (LibraryGuest guest : library.getInfo().getGuests()) { + if (guest.getId() == UUID.fromString("ca4a7abd-95fa-43db-91c7-5d80e27d821a")) { + patrons.add(guest); + } + } + assertThat(patrons).hasSize(1); + var patron = patrons.iterator().next(); + assertThat(patron).isInstanceOf(Patron.class); + assertThat(patron.getName()).isEqualTo("John Book"); + } + + @Test + void testController_returnsNotFoundOnDeletePatron() throws Exception { + mockMvc + .perform( + delete("/patrons/00000000-0000-0000-0000-000000000000") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + } +} From 6395dbc7aaa74969e8e2435154d165a826dff483 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 12:58:01 +0000 Subject: [PATCH 03/11] Fix: Modified test to fit needs of the code --- .../lesson16/web/PatronControllerTest.java | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index bb907886..54a9591c 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -12,6 +12,7 @@ import com.codedifferently.lesson16.library.LibraryGuest; import com.codedifferently.lesson16.library.Patron; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.BeforeAll; @@ -30,54 +31,30 @@ class PatronControllerTest { private static MockMvc mockMvc; @Autowired private Library library; + private Library lib = library; + @BeforeAll static void setUp(WebApplicationContext wac) { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } @Test - void testController_getsAllPatrons() throws Exception { - mockMvc - .perform(get("/patrons").contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.patrons").isArray()) - .andExpect(jsonPath("$.patrons.length()").value(5)); - } - - @Test - void testController_deletesPatron() throws Exception { - Set pat = library.getPatrons(); - UUID ids = UUID.fromString("00000000-0000-0000-0000-000000000000"); - for (LibraryGuest guest : pat) { - if (guest.getName() == "Alice Johnson") { - ids = guest.getId(); - } - } + void testController_getsAnPatron() throws Exception { + List pat = library.getPatrons().stream().toList(); + UUID ids = pat.get(3).getId(); mockMvc - .perform(delete("/patrons/" + ids.toString()).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); - int i = 0; - for (LibraryGuest guest : pat) { - if (guest.getName() == "Alice Johnson") { - i++; - } - } - assertThat(i).isEqualTo(0); + .perform(get("/patrons/" + ids.toString()).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); } @Test - void testController_getsAnPatron() throws Exception { - Set pat = library.getPatrons(); - UUID ids = UUID.fromString("00000000-0000-0000-0000-000000000000"); - for (LibraryGuest guest : pat) { - if (guest.getName() == "Bob Williams") { - ids = guest.getId(); - } - } + void testController_getsAllPatrons() throws Exception { mockMvc - .perform(get("/patrons/" + ids.toString()).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()); + .perform(get("/patrons").contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.patrons").isArray()) + .andExpect(jsonPath("$.patrons.length()").value(5)); } @Test @@ -140,4 +117,37 @@ void testController_returnsNotFoundOnDeletePatron() throws Exception { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } + + @Test + void testController_deletesPatron() throws Exception { + Library lib = library; + List pat = library.getPatrons().stream().toList(); + UUID ids = getGuestId(pat); + + mockMvc + .perform(delete("/patrons/" + ids.toString()).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + int i = 0; + pat = library.getPatrons().stream().toList(); + for (LibraryGuest guest : pat) { + if (guest.getId() == ids) { + i++; + } + } + library = lib; + assertThat(i).isEqualTo(0); + } + + UUID getGuestId(List list) { + if (list.get(0).getCheckedOutMediaItems().size() == 0) { + return list.get(0).getId(); + } else if (list.get(1).getCheckedOutMediaItems().size() == 0) { + return list.get(1).getId(); + } else if (list.get(2).getCheckedOutMediaItems().size() == 0) { + return list.get(2).getId(); + } else if (list.get(3).getCheckedOutMediaItems().size() == 0) { + return list.get(3).getId(); + } + return list.get(4).getId(); + } } From 035b0c9631d9d4713b1bbe1e17baf053024254d8 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 13:06:39 +0000 Subject: [PATCH 04/11] Fix: changed formating --- .../lesson16/web/MediaItemsController.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java index 4242f8f9..4eadb4c6 100644 --- a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java @@ -11,8 +11,8 @@ import java.util.UUID; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -34,7 +34,6 @@ public MediaItemsController(Library library) throws IOException { this.library = library; this.librarian = library.getLibrarians().stream().findFirst().orElseThrow(); } - @GetMapping("/items") public GetMediaItemsResponse getItems() { Set items = library.search(SearchCriteria.builder().build()); @@ -42,7 +41,12 @@ public GetMediaItemsResponse getItems() { var response = GetMediaItemsResponse.builder().items(responseItems).build(); return response; } - + /** + * Post an item to the specified endpoint. + * + * @param req the request object for creating a media item + * @return the response object for creating a media item + */ @PostMapping("/items") public CreateMediaItemResponse postItem(@Valid @RequestBody CreateMediaItemRequest req) { MediaItem media = MediaItemRequest.asMediaItem(req.getItem()); From a96045829bffec455dcc2027f8fc004c7458329a Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 13:07:04 +0000 Subject: [PATCH 05/11] Fix: Re-ran spotless apply --- .../codedifferently/lesson16/web/MediaItemsController.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java index 4eadb4c6..0f4536ce 100644 --- a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/MediaItemsController.java @@ -34,6 +34,7 @@ public MediaItemsController(Library library) throws IOException { this.library = library; this.librarian = library.getLibrarians().stream().findFirst().orElseThrow(); } + @GetMapping("/items") public GetMediaItemsResponse getItems() { Set items = library.search(SearchCriteria.builder().build()); @@ -41,11 +42,12 @@ public GetMediaItemsResponse getItems() { var response = GetMediaItemsResponse.builder().items(responseItems).build(); return response; } + /** * Post an item to the specified endpoint. * - * @param req the request object for creating a media item - * @return the response object for creating a media item + * @param req the request object for creating a media item + * @return the response object for creating a media item */ @PostMapping("/items") public CreateMediaItemResponse postItem(@Valid @RequestBody CreateMediaItemRequest req) { From ba08b1eb7922303145fd705841d29ed1c5bd7de6 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 13:19:28 +0000 Subject: [PATCH 06/11] Fix: Modified tests to closer fit the needs --- .../lesson16/web/PatronControllerTest.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index 54a9591c..4398067b 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -54,7 +54,7 @@ void testController_getsAllPatrons() throws Exception { .perform(get("/patrons").contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.patrons").isArray()) - .andExpect(jsonPath("$.patrons.length()").value(5)); + .andExpect(jsonPath("$.patrons.length()").value(4)); } @Test @@ -139,14 +139,10 @@ void testController_deletesPatron() throws Exception { } UUID getGuestId(List list) { - if (list.get(0).getCheckedOutMediaItems().size() == 0) { - return list.get(0).getId(); - } else if (list.get(1).getCheckedOutMediaItems().size() == 0) { - return list.get(1).getId(); - } else if (list.get(2).getCheckedOutMediaItems().size() == 0) { - return list.get(2).getId(); - } else if (list.get(3).getCheckedOutMediaItems().size() == 0) { - return list.get(3).getId(); + for (LibraryGuest guest : list) { + if (guest.getCheckedOutMediaItems().size() == 0) { + return guest.getId(); + } } return list.get(4).getId(); } From 96b17b2b2a638edf191a0780be1a12afe3fe2b9d Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 14:43:54 +0000 Subject: [PATCH 07/11] Fix: modified the test --- .../lesson16/web/PatronControllerTest.java | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index 4398067b..10fd44d6 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -10,10 +10,7 @@ import com.codedifferently.lesson16.Lesson16; import com.codedifferently.lesson16.library.Library; import com.codedifferently.lesson16.library.LibraryGuest; -import com.codedifferently.lesson16.library.Patron; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -80,33 +77,19 @@ void testController_reportsBadRequestOnAddPatron() throws Exception { @Test void testController_addsPatron() throws Exception { String json = - """ - { - "guests":{ - { - "id": "ca4a7abd-95fa-43db-91c7-5d80e27d821a" - "name": "John Book", - "email": "john.Book@reallibrary.org", - "checkedOutPatrons": [] - } - } - """; + """ + { + "patron":{ + "name": "John Book", + "email": "johk@reallibrary.org", + } + } + """; mockMvc .perform(post("/patrons").contentType(MediaType.APPLICATION_JSON).content(json)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.patron.id").value("ca4a7abd-95fa-43db-91c7-5d80e27d821a")); - - Set patrons = new HashSet<>(); - for (LibraryGuest guest : library.getInfo().getGuests()) { - if (guest.getId() == UUID.fromString("ca4a7abd-95fa-43db-91c7-5d80e27d821a")) { - patrons.add(guest); - } - } - assertThat(patrons).hasSize(1); - var patron = patrons.iterator().next(); - assertThat(patron).isInstanceOf(Patron.class); - assertThat(patron.getName()).isEqualTo("John Book"); + .andExpect(jsonPath("$.patrons.name").value("John Book")); } @Test From 99315c6b71c570fc2b3b149e81a37da0f4b7cdaf Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 14:48:18 +0000 Subject: [PATCH 08/11] Fix: Changed formating --- .../com/codedifferently/lesson16/web/PatronControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index 10fd44d6..33b2eaeb 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -77,7 +77,7 @@ void testController_reportsBadRequestOnAddPatron() throws Exception { @Test void testController_addsPatron() throws Exception { String json = - """ + """ { "patron":{ "name": "John Book", From 51d92f94f273d291cbd7a7a65746c97b1ba8ffac Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Tue, 9 Apr 2024 18:40:02 +0000 Subject: [PATCH 09/11] Fix: Changed json to be correct formating --- .../lesson16/web/PatronControllerTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index 33b2eaeb..bec9ef56 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -51,7 +51,7 @@ void testController_getsAllPatrons() throws Exception { .perform(get("/patrons").contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.patrons").isArray()) - .andExpect(jsonPath("$.patrons.length()").value(4)); + .andExpect(jsonPath("$.patrons.length()").value(5)); } @Test @@ -78,18 +78,18 @@ void testController_reportsBadRequestOnAddPatron() throws Exception { void testController_addsPatron() throws Exception { String json = """ - { - "patron":{ - "name": "John Book", - "email": "johk@reallibrary.org", - } - } - """; + { + "patron":{ + "name": "John Book", + "email": "johk@reallibrary.org" + } + } + """; mockMvc .perform(post("/patrons").contentType(MediaType.APPLICATION_JSON).content(json)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.patrons.name").value("John Book")); + .andExpect(jsonPath("$.patron.name").value("John Book")); } @Test From cd1df88049b7083e671b209689d6a33a4f816270 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Wed, 10 Apr 2024 14:03:07 +0000 Subject: [PATCH 10/11] Chore: Added comments to test and patron test --- .../lesson16/web/PatronsController.java | 15 ++++++++--- .../lesson16/web/PatronControllerTest.java | 25 +++++++++++-------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java index 919101c9..bfd0f2e3 100644 --- a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java @@ -1,14 +1,11 @@ package com.codedifferently.lesson16.web; -import com.codedifferently.lesson16.library.Library; -import com.codedifferently.lesson16.library.LibraryGuest; -import com.codedifferently.lesson16.library.Patron; -import jakarta.validation.Valid; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -19,6 +16,16 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; +import com.codedifferently.lesson16.library.Library; +import com.codedifferently.lesson16.library.LibraryGuest; +import com.codedifferently.lesson16.library.Patron; + +import jakarta.validation.Valid; + +// ___________________________________________________________ +// THIS CODE WAS MADE IN COLLABORATION WITH VICENTE AND RICH +// ___________________________________________________________ + @RestController public class PatronsController { private final Library library; diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index bec9ef56..0d65db22 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -1,17 +1,9 @@ package com.codedifferently.lesson16.web; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.codedifferently.lesson16.Lesson16; -import com.codedifferently.lesson16.library.Library; -import com.codedifferently.lesson16.library.LibraryGuest; import java.util.List; import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -19,9 +11,22 @@ import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import com.codedifferently.lesson16.Lesson16; +import com.codedifferently.lesson16.library.Library; +import com.codedifferently.lesson16.library.LibraryGuest; + +// ___________________________________________________________ +// THIS CODE WAS MADE IN COLLABORATION WITH VICENTE AND RICH +// ___________________________________________________________ + @SpringBootTest @ContextConfiguration(classes = Lesson16.class) class PatronControllerTest { From fc158d684353c6e4f941362f795d07281aaf4240 Mon Sep 17 00:00:00 2001 From: Mohamed <“moibrahi7@gmail.com”> Date: Wed, 10 Apr 2024 14:07:37 +0000 Subject: [PATCH 11/11] Fix: ran spotless apply to fix formating --- .../lesson16/web/PatronsController.java | 11 ++++------ .../lesson16/web/PatronControllerTest.java | 21 +++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java index bfd0f2e3..7fb52e91 100644 --- a/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java +++ b/lesson_16/api/api_app/src/main/java/com/codedifferently/lesson16/web/PatronsController.java @@ -1,11 +1,14 @@ package com.codedifferently.lesson16.web; +import com.codedifferently.lesson16.library.Library; +import com.codedifferently.lesson16.library.LibraryGuest; +import com.codedifferently.lesson16.library.Patron; +import jakarta.validation.Valid; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; - import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -16,12 +19,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; -import com.codedifferently.lesson16.library.Library; -import com.codedifferently.lesson16.library.LibraryGuest; -import com.codedifferently.lesson16.library.Patron; - -import jakarta.validation.Valid; - // ___________________________________________________________ // THIS CODE WAS MADE IN COLLABORATION WITH VICENTE AND RICH // ___________________________________________________________ diff --git a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java index 0d65db22..ac039c19 100644 --- a/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java +++ b/lesson_16/api/api_app/src/test/java/com/codedifferently/lesson16/web/PatronControllerTest.java @@ -1,9 +1,17 @@ package com.codedifferently.lesson16.web; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.codedifferently.lesson16.Lesson16; +import com.codedifferently.lesson16.library.Library; +import com.codedifferently.lesson16.library.LibraryGuest; import java.util.List; import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -11,18 +19,9 @@ import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import com.codedifferently.lesson16.Lesson16; -import com.codedifferently.lesson16.library.Library; -import com.codedifferently.lesson16.library.LibraryGuest; - // ___________________________________________________________ // THIS CODE WAS MADE IN COLLABORATION WITH VICENTE AND RICH // ___________________________________________________________