Add integration tests for inventory controller

This commit is contained in:
Simon Bruder 2023-11-18 14:58:17 +01:00
parent 58dae6532e
commit f7d859b25d
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC

View file

@ -0,0 +1,208 @@
/*
* Copyright (C) 2023 Simon Bruder
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package catering.inventory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.salespointframework.core.Currencies.EURO;
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.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.javamoney.moneta.Money;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.salespointframework.catalog.Product.ProductIdentifier;
import org.salespointframework.inventory.UniqueInventory;
import org.salespointframework.inventory.UniqueInventoryItem;
import org.salespointframework.quantity.Quantity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import catering.catalog.CatalogDummy;
import catering.catalog.CatalogDummyType;
@AutoConfigureMockMvc
@SpringBootTest
class InventoryControllerIntegrationTests {
@Autowired
MockMvc mvc;
@Autowired
UniqueInventory<UniqueInventoryItem> inventory;
UniqueInventoryItem anyInventoryItem;
CatalogDummy anyProduct;
ProductIdentifier anyPid;
@BeforeEach
void populateAnyInventoryItem() {
anyInventoryItem = inventory.findAll().stream().findAny().get();
anyProduct = (CatalogDummy) anyInventoryItem.getProduct();
anyPid = anyProduct.getId();
}
@Test
@WithMockUser(username = "admin", roles = "ADMIN")
void adminCanList() throws Exception {
mvc.perform(get("/inventory"))
.andExpect(status().isOk())
.andExpect(content().string(containsString(anyPid.toString())));
}
@Test
@WithMockUser(username = "admin", roles = "ADMIN")
void adminCanAdd() throws Exception {
mvc.perform(get("/inventory/add"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Produkt anlegen")));
long itemCountBefore = inventory.findAll().stream().count();
mvc.perform(post("/inventory/add")
.param("type", "CONSUMABLE")
.param("name", "MOCK Schnitzel Wiener Art (vegan)")
.param("quantity", "100")
.param("wholesalePrice", "3.00")
.param("retailPrice", "7.50")
.param("promotionPrice", "6.66"))
.andExpect(redirectedUrl("/inventory"));
long itemCountAfter = inventory.findAll().stream().count();
assertThat(itemCountAfter).isEqualTo(itemCountBefore + 1);
// TODO: this must be changed once the catalog split is done
assertThat(inventory.findAll().stream())
.extracting("product.type", "product.name", "quantity", "product.wholesalePrice", "product.price",
"product.promotionPrice")
.contains(tuple(CatalogDummyType.CONSUMABLE, "MOCK Schnitzel Wiener Art (vegan)", Quantity.of(100),
Money.of(3, EURO), Money.of(7.5, EURO), Money.of(6.66, EURO)));
}
@Test
@WithMockUser(username = "admin", roles = "ADMIN")
void adminCanDelete() throws Exception {
long itemCountBefore = inventory.findAll().stream().count();
mvc.perform(get("/inventory/delete/" + anyPid))
.andExpect(redirectedUrl("/inventory"));
long itemCountAfter = inventory.findAll().stream().count();
assertThat(itemCountAfter).isEqualTo(itemCountBefore - 1);
// TODO: this must be changed once the catalog split is done
assertThat(inventory.findAll().stream())
.extracting("product.type", "product.name", "quantity")
.doesNotContain(tuple(anyProduct.getType(), anyProduct.getName(), anyInventoryItem.getQuantity()));
}
@Test
@WithMockUser(username = "admin", roles = "ADMIN")
void adminCanEditConsumable() throws Exception {
// TODO: this must be changed once the catalog split is done
CatalogDummy anyConsumable = inventory.findAll().stream()
.map(UniqueInventoryItem::getProduct)
.map(p -> (CatalogDummy) p)
.filter(cd -> cd.getType().equals(CatalogDummyType.CONSUMABLE))
.findAny()
.get();
mvc.perform(get("/inventory/edit/" + anyConsumable.getId()))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Produkt bearbeiten")));
boolean hasPromotionPrice = anyConsumable.getPromotionPrice() != null;
mvc.perform(post("/inventory/edit/" + anyConsumable.getId())
.param("type", "CONSUMABLE")
.param("name", "MOCK edited")
.param("quantity", "4711")
.param("wholesalePrice", "0.01")
.param("retailPrice", "0.01")
.param("promotionPrice", hasPromotionPrice ? "" : "5"))
.andExpect(redirectedUrl("/inventory"));
UniqueInventoryItem editedInventoryItem = inventory.findByProductIdentifier(anyConsumable.getId()).stream()
.findAny().get();
CatalogDummy editedProduct = (CatalogDummy) editedInventoryItem.getProduct();
assertThat(editedInventoryItem.getQuantity()).isEqualTo(Quantity.of(4711));
assertThat(editedProduct)
.extracting("type", "name", "wholesalePrice", "price", "promotionPrice")
.containsExactly(CatalogDummyType.CONSUMABLE, "MOCK edited", Money.of(0.01, EURO),
Money.of(0.01, EURO), hasPromotionPrice ? null : Money.of(0.01, EURO));
}
/**
* Helper function for asserting that protected endpoints are not accessible by
* unauthentificated users.
*
* @param resultActions the result of
* {@link org.springframework.test.web.servlet.MockMvc#perform}
* @return the {@link ResultActions} given as a parameter to perform more
* matching on
*/
ResultActions assertRedirectsToLogin(ResultActions resultActions) throws Exception {
// Spring security uses the full URL to redirect to login,
// so we cant use redirectedUrl("/login") in this case.
return resultActions
.andExpect(status().is3xxRedirection()) // concrete redirection type is implementation detail
.andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login")));
}
@Test
void disallowUnauthorizedList() throws Exception {
assertRedirectsToLogin(mvc.perform(get("/inventory")));
}
@Test
void disallowUnauthorizedEditPage() throws Exception {
assertRedirectsToLogin(mvc.perform(get("/inventory/edit/" + anyPid)));
}
@Test
void disallowUnauthorizedEdit() throws Exception {
assertRedirectsToLogin(mvc.perform(post("/inventory/edit/" + anyPid)));
}
@Test
void disallowUnauthorizedAddPage() throws Exception {
assertRedirectsToLogin(mvc.perform(get("/inventory/add")));
}
@Test
void disallowUnauthorizedAdd() throws Exception {
assertRedirectsToLogin(mvc.perform(post("/inventory/add")));
}
@Test
void disallowUnauthorizedDelete() throws Exception {
assertRedirectsToLogin(mvc.perform(get("/inventory/delete/" + anyPid)));
}
}