Skip to content

Commit

Permalink
feat: Patron files, only missing test
Browse files Browse the repository at this point in the history
  • Loading branch information
SherllinT committed Apr 11, 2024
1 parent efc6215 commit 489cc2f
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.codedifferently.lesson16.web;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class CreatePatronResponse {
private MediaItemResponse item;
}
Original file line number Diff line number Diff line change
@@ -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<PatronResponse> patron;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.codedifferently.lesson16.web;

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;
private String name;
private String email;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.codedifferently.lesson16.web;

import com.codedifferently.lesson16.library.Patron;
import java.util.UUID;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class PatronResponse {

private UUID id;
private String name;
private String email;

public static PatronResponse from(Patron patron) {
var result =
PatronResponse.builder().id(patron.getId()).name(patron.getName()).email(patron.getEmail());

return result.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.codedifferently.lesson16.web;

import com.codedifferently.lesson16.library.Library;
import com.codedifferently.lesson16.library.Patron;
import com.codedifferently.lesson16.library.search.SearchCriteria;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import main.java.com.codedifferently.lesson16.web.CreatePatronResponse;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PatronsController {
private final Library library;

public PatronsController(Library library) throws IOException {
this.library = library;
}

@GetMapping("/patrons")
public ResponseEntity<List<Patron>> getPatrons(){
Set<Patron> patronsSet = library.getAllPatrons();
List<Patron> patronsList = new ArrayList<>(patronsSet);
return new ResponseEntity<>(patronsList, HttpStatus.OK);
}

@GetMapping("/patron/{id}")
public ResponseEntity<GetPatronsResponse> getPatron(@PathVariable("id") UUID id) {
Patron patron = library.getPatronById(id);
if (patron == null) {
return ResponseEntity.notFound().build();
}
GetPatronsResponse response = GetPatronsResponse.from(patron);
return ResponseEntity.ok(response);
}

@DeleteMapping("/patron/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public ResponseEntity<Void> deletePatron(@PathVariable("id") UUID id) {
if (!library.hasPatron(id)) {
return ResponseEntity.notFound().build();
}
library.removePatron(id);
return ResponseEntity.noContent().build();
}

@PostMapping("/patron")
@ResponseStatus(HttpStatus.CREATED)
public CreatePatronResponse createPatron(@RequestBody CreatePatronRequest request) {
Patron patron = request.getPatron();
library.addPatron(patron);
CreatePatronResponse response = CreatePatronResponse.from(patron);
return response;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
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.Book;
import com.codedifferently.lesson16.library.Library;
import com.codedifferently.lesson16.library.MediaItem;
import com.codedifferently.lesson16.library.search.SearchCriteria;
import java.util.Set;
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 PatronsControllerTest {
private static MockMvc mockMvc;
@Autowired private Library library;

@BeforeAll
static void setUp(WebApplicationContext wac) {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}

@Test
void testController_patronGetsAllItems() throws Exception {
mockMvc
.perform(get("/patrons").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.items").isArray())
.andExpect(jsonPath("$.items.length()").value(31));
}

@Test
void testController_getsAnItem() throws Exception {
mockMvc
.perform(
get("/items/31616162-3831-3832-2d34-3334352d3465")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}

@Test
void testController_returnsNotFoundOnGetItem() throws Exception {
mockMvc
.perform(
get("/items/00000000-0000-0000-0000-000000000000")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}

@Test
void testController_reportsBadRequestOnAddItem() throws Exception {
String json = "{}";

mockMvc
.perform(post("/items").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.errors").isArray())
.andExpect(jsonPath("$.errors.length()").value(1));
}

@Test
void testController_addsItem() throws Exception {
String json =
"""
{
"item": {
"id": "e27a4e0d-9664-420d-955e-c0e295d0ce02",
"type": "BOOK",
"title": "Becoming",
"isbn": "9781524763138",
"authors": ["Michelle Obama"],
"pages": 448
}
}
""";

mockMvc
.perform(post("/items").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isOk())
.andExpect(jsonPath("$.item.id").value("e27a4e0d-9664-420d-955e-c0e295d0ce02"));

Set<MediaItem> items =
library.search(SearchCriteria.builder().id("e27a4e0d-9664-420d-955e-c0e295d0ce02").build());
assertThat(items).hasSize(1);
var item = items.iterator().next();
assertThat(item).isInstanceOf(Book.class);
assertThat(item.getTitle()).isEqualTo("Becoming");
}

@Test
void testController_returnsNotFoundOnDeleteItem() throws Exception {
mockMvc
.perform(
delete("/items/00000000-0000-0000-0000-000000000000")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}

@Test
void testController_deletesItem() throws Exception {
mockMvc
.perform(
delete("/items/32623932-6566-3364-2d62-3232342d3435")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent());

Set<MediaItem> items =
library.search(SearchCriteria.builder().id("32623932-6566-3364-2d62-3232342d3435").build());
assertThat(items).hasSize(0);
}
}

0 comments on commit 489cc2f

Please sign in to comment.