diff --git a/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java b/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java index 24a9564..f86cb35 100644 --- a/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java +++ b/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java @@ -21,6 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.math.BigDecimal; import java.util.Optional; import java.util.Set; @@ -59,11 +60,12 @@ class InventoryControllerIntegrationTests { @Autowired CateringCatalog catalog; - UniqueInventoryItem anyInventoryItem; - Product anyProduct; - ProductIdentifier anyPid; UniqueInventoryItem anyConsumableItem; UniqueInventoryItem anyRentableItem; + Consumable anyConsumable; + Rentable anyRentable; + ProductIdentifier anyConsumableId; + ProductIdentifier anyRentableId; UniqueInventoryItem anyItemOf(Class type) { switch (type.getSimpleName()) { @@ -80,11 +82,28 @@ class InventoryControllerIntegrationTests { return inventory.findAll().stream().count(); } + /** + * Functional interface for comparing two {@link BigDecimal}s. + * + * It can be used for jUnit tests with + * {@code .withEqualsForType(InventoryControllerIntegrationTests::compareBigDecimal, BigDecimal.class)}. + * + * This is required when comparing {@link Quantity}s with a {@link Metric} of + * {@link Metric#LITER}. + * + * @param a {@link BigDecimal} + * @param b {@link BigDecimal} + * @return {@literal true} if they are equal, {@literal false} if not + */ + private static boolean compareBigDecimal(BigDecimal a, BigDecimal b) { + return a.compareTo(b) == 0; + } + @BeforeEach void populateAnyInventoryItem() { - anyInventoryItem = inventory.findAll().stream().findAny().get(); - anyProduct = anyInventoryItem.getProduct(); - anyPid = anyProduct.getId(); + inventory.deleteAll(); + catalog.deleteAll(); + anyConsumableItem = inventory.save(new UniqueInventoryItem( catalog.save(new Consumable("Any Consumable", Money.of(1, EURO), Money.of(0.5, EURO), Optional.of(Money.of(0.75, EURO)), Set.of(OrderType.EVENT_CATERING, OrderType.PARTY_SERVICE), @@ -94,102 +113,339 @@ class InventoryControllerIntegrationTests { catalog.save(new Rentable("Any Rentable", Money.of(1, EURO), Money.of(0.5, EURO), Set.of(OrderType.EVENT_CATERING, OrderType.PARTY_SERVICE), Metric.UNIT)), Quantity.of(1))); + + anyConsumable = (Consumable) anyConsumableItem.getProduct(); + anyRentable = (Rentable) anyRentableItem.getProduct(); + + anyConsumableId = anyConsumable.getId(); + anyRentableId = anyRentable.getId(); } + void updateAnies() { + anyConsumableItem = inventory.findById(anyConsumableItem.getId()).get(); + anyRentableItem = inventory.findById(anyRentableItem.getId()).get(); + + anyConsumable = (Consumable) anyConsumableItem.getProduct(); + anyRentable = (Rentable) anyRentableItem.getProduct(); + } + + /* + * Tests for listing + */ + @Test @WithMockUser(username = "admin", roles = "ADMIN") void adminCanList() throws Exception { mvc.perform(get("/inventory")) .andExpect(status().isOk()) - .andExpect(content().string(containsString(anyPid.toString()))); + .andExpect(content().string(containsString(anyConsumableItem.getProduct().getName()))); + } + + /* + * Tests for adding + */ + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanReachAddConsumablePage() throws Exception { + mvc.perform(get("/inventory/add") + .queryParam("type", Consumable.class.getSimpleName())) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("Produkt anlegen"))); } @Test @WithMockUser(username = "admin", roles = "ADMIN") - void adminCanAddConsumable() throws Exception { - mvc.perform(get("/inventory/add?type=Consumable")) + void adminCanReachAddRentablePage() throws Exception { + mvc.perform(get("/inventory/add") + .queryParam("type", Rentable.class.getSimpleName())) .andExpect(status().isOk()) .andExpect(content().string(containsString("Produkt anlegen"))); + } + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantReachAddInvalidPage() throws Exception { + mvc.perform(get("/inventory/add") + .queryParam("type", "INVALID")) + .andExpect(status().is3xxRedirection()); // not good error handling + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanAddConsumableWithoutPromotion() throws Exception { long itemCountBefore = countItems(); - mvc.perform(post("/inventory/add?type=Consumable") + mvc.perform(post("/inventory/add") .queryParam("type", Consumable.class.getSimpleName()) - .param("name", "MOCK Schnitzel Wiener Art (vegan)") + .param("name", "Added Consumable") .param("quantity", "100") - .param("orderTypes", "MOBILE_BREAKFAST", "PARTY_SERVICE") + .param("orderTypes", "EVENT_CATERING", "MOBILE_BREAKFAST", "PARTY_SERVICE") .param("wholesalePrice", "3.00") .param("retailPrice", "7.50") - .param("promotionPrice", "6.66")) + .param("metric", "UNIT")) .andExpect(redirectedUrl("/inventory")); assertThat(countItems()).isEqualTo(itemCountBefore + 1); - // extracting is not possible here, as the category sets are not equal assertThat(inventory.findAll().stream() - .filter(ie -> ie.getProduct().getName().equals("MOCK Schnitzel Wiener Art (vegan)")).findAny()) + .filter(ie -> ie.getProduct().getName().equals("Added Consumable")).findAny()) .get() .usingRecursiveComparison() .ignoringFields("inventoryItemIdentifier.inventoryItemId", "isNew", "product.id.productId", "product.isNew") .isEqualTo( - new UniqueInventoryItem(new Consumable("MOCK Schnitzel Wiener Art (vegan)", Money.of(7.5, EURO), - Money.of(3, EURO), Optional.of(Money.of(6.66, EURO)), - Set.of(OrderType.MOBILE_BREAKFAST, OrderType.PARTY_SERVICE), Metric.UNIT), + new UniqueInventoryItem(new Consumable("Added Consumable", + Money.of(7.5, EURO), + Money.of(3, EURO), + Optional.empty(), + Set.of(OrderType.EVENT_CATERING, OrderType.MOBILE_BREAKFAST, OrderType.PARTY_SERVICE), + Metric.UNIT), Quantity.of(100))); } @Test @WithMockUser(username = "admin", roles = "ADMIN") - void adminCanDelete() throws Exception { + void adminCanAddConsumableWithPromotion() throws Exception { long itemCountBefore = countItems(); - mvc.perform(get("/inventory/delete/" + anyPid)) + mvc.perform(post("/inventory/add") + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", "Added Consumable") + .param("quantity", "99") + .param("orderTypes", "PARTY_SERVICE") + .param("wholesalePrice", "4.00") + .param("retailPrice", "7.00") + .param("promotionPrice", "5.00") + .param("metric", "LITER")) .andExpect(redirectedUrl("/inventory")); - assertThat(countItems()).isEqualTo(itemCountBefore - 1); + assertThat(countItems()).isEqualTo(itemCountBefore + 1); - assertThat(inventory.findAll().stream()) - .extracting("product.name", "quantity") - .doesNotContain(tuple(anyProduct.getName(), anyInventoryItem.getQuantity())); + assertThat(inventory.findAll().stream() + .filter(ie -> ie.getProduct().getName().equals("Added Consumable")).findAny()) + .get() + .usingRecursiveComparison() + .withEqualsForType(InventoryControllerIntegrationTests::compareBigDecimal, BigDecimal.class) + .ignoringFields("inventoryItemIdentifier.inventoryItemId", "isNew", "product.id.productId", + "product.isNew") + .isEqualTo( + new UniqueInventoryItem(new Consumable("Added Consumable", + Money.of(7, EURO), + Money.of(4, EURO), + Optional.of(Money.of(5, EURO)), + Set.of(OrderType.PARTY_SERVICE), + Metric.LITER), + Quantity.of(99, Metric.LITER))); } @Test @WithMockUser(username = "admin", roles = "ADMIN") - void adminCanEditConsumable() throws Exception { - Consumable anyConsumable = inventory.findAll().stream() - .map(UniqueInventoryItem::getProduct) - .filter(Consumable.class::isInstance) - .map(Consumable.class::cast) - .findAny() - .get(); + void adminCanAddRentable() throws Exception { + long itemCountBefore = countItems(); - mvc.perform( - get("/inventory/edit/" + anyConsumable.getId())) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Produkt bearbeiten"))); - - mvc.perform(post("/inventory/edit/" + anyConsumable.getId()) - .queryParam("type", Consumable.class.getSimpleName()) - .param("type", "CONSUMABLE") - .param("name", "MOCK edited") - .param("orderTypes", "PARTY_SERVICE", "EVENT_CATERING") - .param("quantity", "4711") - .param("wholesalePrice", "0.01") - .param("retailPrice", "0.03") - .param("promotionPrice", "0.02")) + mvc.perform(post("/inventory/add") + .queryParam("type", Rentable.class.getSimpleName()) + .param("name", "Added Rentable") + .param("quantity", "8") + .param("orderTypes", "MOBILE_BREAKFAST") + .param("wholesalePrice", "1000.00") + .param("retailPrice", "10.25") + .param("metric", "UNIT")) .andExpect(redirectedUrl("/inventory")); - UniqueInventoryItem editedInventoryItem = inventory.findByProductIdentifier(anyConsumable.getId()).stream() - .findAny().get(); - Consumable editedProduct = (Consumable) editedInventoryItem.getProduct(); + assertThat(countItems()).isEqualTo(itemCountBefore + 1); - assertThat(editedInventoryItem.getQuantity()).isEqualTo(Quantity.of(4711)); - assertThat(editedProduct) - .extracting("name", "wholesalePrice", "retailPrice", "promotionPrice") - .containsExactly("MOCK edited", Money.of(0.01, EURO), - Money.of(0.03, EURO), Optional.of(Money.of(0.02, EURO))); - assertThat(editedProduct.getCategories()).containsExactlyInAnyOrder("PARTY_SERVICE", "EVENT_CATERING"); + assertThat(inventory.findAll().stream() + .filter(ie -> ie.getProduct().getName().equals("Added Rentable")).findAny()) + .get() + .usingRecursiveComparison() + .ignoringFields("inventoryItemIdentifier.inventoryItemId", "isNew", "product.id.productId", + "product.isNew") + .isEqualTo( + new UniqueInventoryItem(new Rentable("Added Rentable", + Money.of(10.25, EURO), + Money.of(1000.00, EURO), + Set.of(OrderType.MOBILE_BREAKFAST), + Metric.UNIT), + Quantity.of(8))); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantAddConsumableWithEmptyFields() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", "") + .param("quantity", "") + .param("orderTypes", "") + .param("wholesalePrice", "") + .param("retailPrice", "") + .param("promotionPrice", "") + .param("metric", "")) + .andExpect(content().string(containsString("Ungültiger Name"))) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(not(containsString("Ungültiger Buchungstyp")))) // can be empty set + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(not(containsString("Ungültiger Aktionspreis")))) // optional + .andExpect(content().string(containsString("Ungültige Einheit"))); + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantAddRentableWithEmptyFields() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Rentable.class.getSimpleName()) + .param("name", "") + .param("quantity", "") + .param("orderTypes", "") + .param("wholesalePrice", "") + .param("retailPrice", "") + .param("metric", "")) + .andExpect(content().string(containsString("Ungültiger Name"))) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(not(containsString("Ungültiger Buchungstyp")))) // can be empty set + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(containsString("Ungültige Einheit"))); + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantAddConsumableWithMissingFields() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Consumable.class.getSimpleName())) + .andExpect(content().string(containsString("Ungültiger Name"))) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(containsString("Ungültiger Buchungstyp"))) + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(not(containsString("Ungültiger Aktionspreis")))) // optional + .andExpect(content().string(not(containsString("Ungültige Einheit")))); // "" can be cast to Metric.UNIT + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantAddRentableWithMissingFields() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Rentable.class.getSimpleName())) + .andExpect(content().string(containsString("Ungültiger Name"))) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(containsString("Ungültiger Buchungstyp"))) + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(not(containsString("Ungültige Einheit")))); // "" can be cast to Metric.UNIT + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantAddConsumableWithNegativeNumbers() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", "Added Consumable") + .param("quantity", "-12") + .param("orderTypes", "EVENT_CATERING") + .param("wholesalePrice", "-4.20") + .param("retailPrice", "-2.31") + .param("promotionPrice", "-7.14") + .param("metric", "LITER")) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Aktionspreis"))); + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCantAddRentableWithNegativeNumbers() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Rentable.class.getSimpleName()) + .param("name", "Added Rentable") + .param("quantity", "-5") + .param("orderTypes", "MOBILE_BREAKFAST") + .param("wholesalePrice", "-589.12") + .param("retailPrice", "-12.40") + .param("metric", "UNIT")) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))); + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanAddConsumableWithZeroes() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", "Added Consumable") + .param("quantity", "0") + .param("orderTypes", "EVENT_CATERING") + .param("wholesalePrice", "0") + .param("retailPrice", "0") + .param("promotionPrice", "0") + .param("metric", "UNIT")) + .andExpect(content().string(not(containsString("Ungültige Menge")))) + .andExpect(content().string(not(containsString("Ungültiger Einkaufspreis")))) + .andExpect(content().string(not(containsString("Ungültiger Verkaufspreis")))) + .andExpect(content().string(not(containsString("Ungültiger Aktionspreis")))); + + assertThat(countItems()).isEqualTo(itemCountBefore + 1); + + assertThat(inventory.findAll().stream().filter(i -> i.getProduct() instanceof Consumable)) + .extracting("product.name", "quantity", "product.wholesalePrice", "product.retailPrice", + "product.promotionPrice") + .contains(tuple("Added Consumable", Quantity.of(0), Money.of(0, EURO), Money.of(0, EURO), + Optional.of(Money.of(0, EURO)))); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanAddRentableWithZeroes() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/add") + .queryParam("type", Rentable.class.getSimpleName()) + .param("name", "Added Rentable") + .param("quantity", "0") + .param("orderTypes", "MOBILE_BREAKFAST") + .param("wholesalePrice", "0") + .param("retailPrice", "0") + .param("metric", "UNIT")) + .andExpect(content().string(not(containsString("Ungültige Menge")))) + .andExpect(content().string(not(containsString("Ungültiger Einkaufspreis")))) + .andExpect(content().string(not(containsString("Ungültiger Verkaufspreis")))); + + assertThat(countItems()).isEqualTo(itemCountBefore + 1); + + assertThat(inventory.findAll().stream()) + .extracting("product.name", "quantity", "product.wholesalePrice", "product.retailPrice") + .contains(tuple("Added Rentable", Quantity.of(0), Money.of(0, EURO), Money.of(0, EURO))); } @Test @@ -216,16 +472,165 @@ class InventoryControllerIntegrationTests { .andExpect(content().string(not(containsString("Ungültiger Angebotspreis")))); } + /* + * Tests for editing + */ + @Test @WithMockUser(username = "admin", roles = "ADMIN") - void invalidEditReturnsNiceError() throws Exception { - mvc.perform(post("/inventory/edit/" + anyPid) + void adminCanReachEditConsumablePage() throws Exception { + mvc.perform(get("/inventory/edit/" + anyConsumableId) + .queryParam("type", Consumable.class.getSimpleName())) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("Produkt bearbeiten"))) + .andExpect(content().string(containsString(anyConsumable.getName()))); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanReachEditRentablePage() throws Exception { + mvc.perform(get("/inventory/edit/" + anyRentableId) + .queryParam("type", Rentable.class.getSimpleName())) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("Produkt bearbeiten"))) + .andExpect(content().string(containsString(anyRentable.getName()))); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanEditConsumable() throws Exception { + mvc.perform(post("/inventory/edit/" + anyConsumableId) .queryParam("type", Consumable.class.getSimpleName()) - .param("name", "") - .param("quantity", "10") - .param("wholesalePrice", "1.00") - .param("retailPrice", "2.00")) - .andExpect(content().string(containsString("Ungültiger Name"))); + .param("name", "Edited Consumable") + .param("orderTypes", "PARTY_SERVICE", "MOBILE_BREAKFAST") + .param("quantity", "95") + .param("wholesalePrice", "10") + .param("retailPrice", "20") + .param("promotionPrice", "17")) + .andExpect(redirectedUrl("/inventory")); + + updateAnies(); + + assertThat(anyConsumableItem.getQuantity()).isEqualTo(Quantity.of(95)); + assertThat(anyConsumable) + .extracting("name", "wholesalePrice", "retailPrice", "promotionPrice") + .containsExactly("Edited Consumable", Money.of(10, EURO), Money.of(20, EURO), + Optional.of(Money.of(17, EURO))); + assertThat(anyConsumable.getCategories()).containsExactlyInAnyOrder("PARTY_SERVICE", "MOBILE_BREAKFAST"); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanEditRentable() throws Exception { + mvc.perform(post("/inventory/edit/" + anyConsumableId) + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", "Edited Rentable") + .param("orderTypes", "PARTY_SERVICE", "MOBILE_BREAKFAST") + .param("quantity", "95") + .param("wholesalePrice", "10") + .param("retailPrice", "20")) + .andExpect(redirectedUrl("/inventory")); + + updateAnies(); + + assertThat(anyConsumableItem.getQuantity()).isEqualTo(Quantity.of(95)); + assertThat(anyConsumable) + .extracting("name", "wholesalePrice", "retailPrice") + .containsExactly("Edited Rentable", Money.of(10, EURO), Money.of(20, EURO)); + assertThat(anyConsumable.getCategories()).containsExactlyInAnyOrder("PARTY_SERVICE", "MOBILE_BREAKFAST"); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanEditConsumablePromo() throws Exception { + mvc.perform(post("/inventory/edit/" + anyConsumableId) + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", anyConsumable.getName()) + .param("orderTypes", anyConsumable.getCategories().stream().toList().toArray(new String[0])) + .param("quantity", anyConsumableItem.getQuantity().getAmount().toString()) + .param("wholesalePrice", anyConsumable.getWholesalePrice().getNumber().toString()) + .param("retailPrice", anyConsumable.getRetailPrice().getNumber().toString()) + .param("promotionPrice", "")) + .andExpect(redirectedUrl("/inventory")); + + updateAnies(); + + assertThat(anyConsumable.getPromotionPrice()).isEmpty(); + + mvc.perform(post("/inventory/edit/" + anyConsumableId) + .queryParam("type", Consumable.class.getSimpleName()) + .param("name", anyConsumable.getName()) + .param("orderTypes", anyConsumable.getCategories().stream().toList().toArray(new String[0])) + .param("quantity", anyConsumableItem.getQuantity().getAmount().toString()) + .param("wholesalePrice", anyConsumable.getWholesalePrice().getNumber().toString()) + .param("retailPrice", anyConsumable.getRetailPrice().getNumber().toString()) + .param("promotionPrice", "7")) + .andExpect(redirectedUrl("/inventory")); + + updateAnies(); + + assertThat(anyConsumable.getPromotionPrice()).get().isEqualTo(Money.of(7, EURO)); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanEditConsumableWithMissingFields() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/edit/" + anyConsumableId) + .queryParam("type", Consumable.class.getSimpleName())) + .andExpect(content().string(containsString("Ungültiger Name"))) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(containsString("Ungültiger Buchungstyp"))) + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(not(containsString("Ungültiger Aktionspreis")))) // optional + .andExpect(content().string(not(containsString("Ungültige Einheit")))); // "" can be cast to Metric.UNIT + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanEditRentableWithMissingFields() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(post("/inventory/edit/" + anyRentableId) + .queryParam("type", Rentable.class.getSimpleName())) + .andExpect(content().string(containsString("Ungültiger Name"))) + .andExpect(content().string(containsString("Ungültige Menge"))) + .andExpect(content().string(containsString("Ungültiger Buchungstyp"))) + .andExpect(content().string(containsString("Ungültiger Einkaufspreis"))) + .andExpect(content().string(containsString("Ungültiger Verkaufspreis"))) + .andExpect(content().string(not(containsString("Ungültige Einheit")))); // "" can be cast to Metric.UNIT + + assertThat(countItems()).isEqualTo(itemCountBefore); + } + + // tests for editing + // with all fields empty, + // all prices negative + // and all prices zero + // are omitted for brevity, + // as they are essentially the same as with adding + + /* + * Tests for deleting + */ + + @Test + @WithMockUser(username = "admin", roles = "ADMIN") + void adminCanDelete() throws Exception { + long itemCountBefore = countItems(); + + mvc.perform(get("/inventory/delete/" + anyConsumableId)) + .andExpect(redirectedUrl("/inventory")); + + assertThat(countItems()).isEqualTo(itemCountBefore - 1); + + assertThat(inventory.findAll().stream()) + .extracting("product.name", "quantity") + .doesNotContain(tuple(anyConsumable.getName(), anyConsumableItem.getQuantity())); } /* @@ -340,6 +745,6 @@ class InventoryControllerIntegrationTests { @Test void checkPermissionsForDelete() throws Exception { - checkPermissions(get("/inventory/delete/" + anyPid), LOGIN, FORBIDDEN, OVERVIEW); + checkPermissions(get("/inventory/delete/" + anyConsumableId), LOGIN, FORBIDDEN, OVERVIEW); } }