Adds backend endpoints and frontend edit page so pending orders can be updated or soft-cancelled without admin intervention. Co-authored-by: Cursor <cursoragent@cursor.com>
279 lines
11 KiB
Java
279 lines
11 KiB
Java
package se.bilhalsning.controller;
|
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.Mockito.when;
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
|
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 java.time.Instant;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.UUID;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.boot.test.context.SpringBootTest;
|
|
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
|
import org.springframework.security.test.context.support.WithMockUser;
|
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
|
import org.springframework.test.web.servlet.MockMvc;
|
|
import se.bilhalsning.dto.OrderResponse;
|
|
import se.bilhalsning.entity.User;
|
|
import se.bilhalsning.service.OrderService;
|
|
import se.bilhalsning.service.UserService;
|
|
|
|
@SpringBootTest
|
|
@AutoConfigureMockMvc
|
|
class OrderControllerTest {
|
|
|
|
@Autowired
|
|
private MockMvc mockMvc;
|
|
|
|
@MockitoBean
|
|
private OrderService orderService;
|
|
|
|
@MockitoBean
|
|
private UserService userService;
|
|
|
|
@Test
|
|
void shouldReturn403WhenNotAuthenticated() throws Exception {
|
|
mockMvc.perform(get("/api/orders"))
|
|
.andExpect(status().isForbidden());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldReturnOrdersForAuthenticatedUser() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
when(orderService.getOrdersByUserId(userId)).thenReturn(List.of());
|
|
|
|
mockMvc.perform(get("/api/orders"))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$").isArray())
|
|
.andExpect(jsonPath("$").isEmpty());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldReturnOrderWithAllFields() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
se.bilhalsning.entity.Order order = new se.bilhalsning.entity.Order();
|
|
order.setId(UUID.fromString("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"));
|
|
order.setUserId(userId);
|
|
order.setPlate("ABC123");
|
|
order.setLetterText("Test letter");
|
|
order.setStatus(se.bilhalsning.entity.OrderStatus.SENT);
|
|
order.setTrackingId("PN123456789");
|
|
|
|
when(orderService.getOrdersByUserId(userId)).thenReturn(List.of(order));
|
|
|
|
mockMvc.perform(get("/api/orders"))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$[0].id").value("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
|
.andExpect(jsonPath("$[0].plate").value("ABC123"))
|
|
.andExpect(jsonPath("$[0].letterText").value("Test letter"))
|
|
.andExpect(jsonPath("$[0].status").value("sent"))
|
|
.andExpect(jsonPath("$[0].trackingId").value("PN123456789"));
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "unknown@example.com")
|
|
void shouldReturn401WhenUserNotFound() throws Exception {
|
|
when(userService.findByEmail("unknown@example.com")).thenReturn(Optional.empty());
|
|
|
|
mockMvc.perform(get("/api/orders"))
|
|
.andExpect(status().isUnauthorized());
|
|
}
|
|
|
|
@Test
|
|
void shouldReturn403WhenPostingWithoutAuth() throws Exception {
|
|
mockMvc.perform(post("/api/orders")
|
|
.contentType("application/json")
|
|
.content("{\"plate\":\"ABC123\",\"letterText\":\"Hej\"}"))
|
|
.andExpect(status().isForbidden());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldCreateOrderSuccessfully() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
se.bilhalsning.entity.Order savedOrder = new se.bilhalsning.entity.Order();
|
|
savedOrder.setId(UUID.fromString("d1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"));
|
|
savedOrder.setUserId(userId);
|
|
savedOrder.setPlate("ABC123");
|
|
savedOrder.setLetterText("Hej fin bil!");
|
|
savedOrder.setStatus(se.bilhalsning.entity.OrderStatus.PENDING_PAYMENT);
|
|
|
|
when(orderService.createOrder(userId, "ABC123", "Hej fin bil!"))
|
|
.thenReturn(savedOrder);
|
|
|
|
mockMvc.perform(post("/api/orders")
|
|
.contentType("application/json")
|
|
.content("{\"plate\":\"ABC123\",\"letterText\":\"Hej fin bil!\"}"))
|
|
.andExpect(status().isCreated())
|
|
.andExpect(jsonPath("$.id").value("d1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
|
.andExpect(jsonPath("$.plate").value("ABC123"))
|
|
.andExpect(jsonPath("$.letterText").value("Hej fin bil!"))
|
|
.andExpect(jsonPath("$.status").value("pending_payment"));
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldRejectInvalidPlateFormat() throws Exception {
|
|
mockMvc.perform(post("/api/orders")
|
|
.contentType("application/json")
|
|
.content("{\"plate\":\"INVALID\",\"letterText\":\"Hej\"}"))
|
|
.andExpect(status().isBadRequest())
|
|
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("Ogiltigt registreringsnummer")));
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldRejectEmptyLetterText() throws Exception {
|
|
mockMvc.perform(post("/api/orders")
|
|
.contentType("application/json")
|
|
.content("{\"plate\":\"ABC123\",\"letterText\":\"\"}"))
|
|
.andExpect(status().isBadRequest());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldRejectLetterTextOver1000Chars() throws Exception {
|
|
String longText = "a".repeat(1001);
|
|
mockMvc.perform(post("/api/orders")
|
|
.contentType("application/json")
|
|
.content("{\"plate\":\"ABC123\",\"letterText\":\"" + longText + "\"}"))
|
|
.andExpect(status().isBadRequest());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldGetSingleOrderForOwner() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
UUID orderId = UUID.fromString("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
se.bilhalsning.entity.Order order = new se.bilhalsning.entity.Order();
|
|
order.setId(orderId);
|
|
order.setUserId(userId);
|
|
order.setPlate("ABC123");
|
|
order.setLetterText("Test letter");
|
|
order.setStatus(se.bilhalsning.entity.OrderStatus.PENDING_PAYMENT);
|
|
|
|
when(orderService.getOrderById(orderId)).thenReturn(order);
|
|
|
|
mockMvc.perform(get("/api/orders/" + orderId))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.id").value(orderId.toString()))
|
|
.andExpect(jsonPath("$.plate").value("ABC123"))
|
|
.andExpect(jsonPath("$.status").value("pending_payment"));
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldReturn404WhenGettingOtherUsersOrder() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
UUID orderId = UUID.fromString("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
se.bilhalsning.entity.Order order = new se.bilhalsning.entity.Order();
|
|
order.setId(orderId);
|
|
order.setUserId(UUID.randomUUID());
|
|
|
|
when(orderService.getOrderById(orderId)).thenReturn(order);
|
|
|
|
mockMvc.perform(get("/api/orders/" + orderId))
|
|
.andExpect(status().isNotFound());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldPatchOrderSuccessfully() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
UUID orderId = UUID.fromString("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
se.bilhalsning.entity.Order order = new se.bilhalsning.entity.Order();
|
|
order.setId(orderId);
|
|
order.setUserId(userId);
|
|
order.setPlate("ABC123");
|
|
order.setLetterText("Updated text");
|
|
order.setStatus(se.bilhalsning.entity.OrderStatus.PENDING_PAYMENT);
|
|
|
|
when(orderService.updatePendingOrder(any(), any(), any())).thenReturn(order);
|
|
|
|
mockMvc.perform(patch("/api/orders/" + orderId)
|
|
.contentType("application/json")
|
|
.content("{\"letterText\":\"Updated text\"}"))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.letterText").value("Updated text"));
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldRejectPatchWithEmptyLetterText() throws Exception {
|
|
UUID orderId = UUID.fromString("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
|
|
mockMvc.perform(patch("/api/orders/" + orderId)
|
|
.contentType("application/json")
|
|
.content("{\"letterText\":\"\"}"))
|
|
.andExpect(status().isBadRequest());
|
|
}
|
|
|
|
@Test
|
|
@WithMockUser(username = "test@bilhej.se")
|
|
void shouldCancelOrderSuccessfully() throws Exception {
|
|
UUID userId = UUID.fromString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
UUID orderId = UUID.fromString("c1eebc99-9c0b-4ef8-bb6d-6bb9bd380a11");
|
|
User user = new User();
|
|
user.setId(userId);
|
|
user.setEmail("test@bilhej.se");
|
|
|
|
when(userService.findByEmail("test@bilhej.se")).thenReturn(Optional.of(user));
|
|
|
|
se.bilhalsning.entity.Order order = new se.bilhalsning.entity.Order();
|
|
order.setId(orderId);
|
|
order.setUserId(userId);
|
|
order.setPlate("ABC123");
|
|
order.setLetterText("Test letter");
|
|
order.setStatus(se.bilhalsning.entity.OrderStatus.CANCELLED);
|
|
|
|
when(orderService.cancelOrder(orderId, userId)).thenReturn(order);
|
|
|
|
mockMvc.perform(post("/api/orders/" + orderId + "/cancel"))
|
|
.andExpect(status().isOk())
|
|
.andExpect(jsonPath("$.status").value("cancelled"));
|
|
}
|
|
}
|