diff --git a/.gitignore b/.gitignore index 3256422..7a88376 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ build/ .vscode/ ### Custom ### -db/mysql \ No newline at end of file +/db/mysql +/db/testmysql/ diff --git a/http-requests/category.http b/http-requests/category.http index 0df78f1..ded307c 100644 --- a/http-requests/category.http +++ b/http-requests/category.http @@ -6,7 +6,8 @@ Content-Type: application/json { "name": "Erwachsene", "price": 25.5, - "stock": 100 + "stock": 100, + "eventId": 1 } ### update diff --git a/src/main/java/me/jweissen/aeticket/controller/CategoryController.java b/src/main/java/me/jweissen/aeticket/controller/CategoryController.java index 9385e2a..4ac22bc 100644 --- a/src/main/java/me/jweissen/aeticket/controller/CategoryController.java +++ b/src/main/java/me/jweissen/aeticket/controller/CategoryController.java @@ -47,11 +47,17 @@ public class CategoryController { responseCode = "403", description = "You're not authorized to perform this operation." ), + @ApiResponse( + responseCode = "404", + description = "The given eventId couldn't be found" + ), }) @PostMapping("/create") @AdminOnly public ResponseEntity create(@RequestBody CategoryRequestDto dto) { - categoryService.create(dto); + if (!categoryService.create(dto)) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } return ResponseEntity.status(HttpStatus.CREATED).build(); } diff --git a/src/main/java/me/jweissen/aeticket/dto/request/CategoryRequestDto.java b/src/main/java/me/jweissen/aeticket/dto/request/CategoryRequestDto.java index 53d0af4..e802e7f 100644 --- a/src/main/java/me/jweissen/aeticket/dto/request/CategoryRequestDto.java +++ b/src/main/java/me/jweissen/aeticket/dto/request/CategoryRequestDto.java @@ -1,4 +1,4 @@ package me.jweissen.aeticket.dto.request; -public record CategoryRequestDto(String name, Double price, Integer stock) { +public record CategoryRequestDto(String name, Double price, Integer stock, Long eventId) { } diff --git a/src/main/java/me/jweissen/aeticket/model/Cart.java b/src/main/java/me/jweissen/aeticket/model/Cart.java index 62876a5..aa733a6 100644 --- a/src/main/java/me/jweissen/aeticket/model/Cart.java +++ b/src/main/java/me/jweissen/aeticket/model/Cart.java @@ -1,8 +1,7 @@ package me.jweissen.aeticket.model; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; import java.util.List; @@ -10,6 +9,9 @@ import java.util.List; @Table @Getter @Setter +@AllArgsConstructor +@NoArgsConstructor +@Builder public class Cart { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/me/jweissen/aeticket/model/User.java b/src/main/java/me/jweissen/aeticket/model/User.java index 2398d0f..1eb403e 100644 --- a/src/main/java/me/jweissen/aeticket/model/User.java +++ b/src/main/java/me/jweissen/aeticket/model/User.java @@ -10,6 +10,8 @@ import java.util.List; @Table @RequiredArgsConstructor @NoArgsConstructor +@Builder +@AllArgsConstructor @Getter @Setter public class User { diff --git a/src/main/java/me/jweissen/aeticket/service/CategoryService.java b/src/main/java/me/jweissen/aeticket/service/CategoryService.java index 8006854..9098f46 100644 --- a/src/main/java/me/jweissen/aeticket/service/CategoryService.java +++ b/src/main/java/me/jweissen/aeticket/service/CategoryService.java @@ -3,9 +3,10 @@ package me.jweissen.aeticket.service; import me.jweissen.aeticket.dto.request.CategoryRequestDto; import me.jweissen.aeticket.dto.request.CategoryUpdateRequestDto; import me.jweissen.aeticket.dto.response.CategoryResponseDto; -import me.jweissen.aeticket.dto.response.EventResponseDto; import me.jweissen.aeticket.model.Category; +import me.jweissen.aeticket.model.Event; import me.jweissen.aeticket.repository.CategoryRepository; +import me.jweissen.aeticket.repository.EventRepository; import org.springframework.stereotype.Service; import java.util.List; @@ -14,9 +15,11 @@ import java.util.Optional; @Service public class CategoryService { private final CategoryRepository categoryRepository; + private final EventRepository eventRepository; - public CategoryService(CategoryRepository categoryRepository) { + public CategoryService(CategoryRepository categoryRepository, EventRepository eventRepository) { this.categoryRepository = categoryRepository; + this.eventRepository = eventRepository; } public static Category fromDto(CategoryRequestDto dto) { @@ -52,9 +55,16 @@ public class CategoryService { return (Double.valueOf(euros * 100)).intValue(); } - public CategoryResponseDto create(CategoryRequestDto dto) { - Category category = categoryRepository.save(fromDto(dto)); - return toDto(category); + public boolean create(CategoryRequestDto dto) { + Category category = fromDto(dto); + Optional event = eventRepository.findById(dto.eventId()); + if (event.isEmpty()) { + // event ids not found + return false; + } + category.setEvent(event.get()); + categoryRepository.save(category); + return true; } public boolean update(CategoryUpdateRequestDto dto) { diff --git a/src/test/java/me/jweissen/aeticket/controller/CartControllerTest.java b/src/test/java/me/jweissen/aeticket/controller/CartControllerTest.java index 2d98ec6..9471c92 100644 --- a/src/test/java/me/jweissen/aeticket/controller/CartControllerTest.java +++ b/src/test/java/me/jweissen/aeticket/controller/CartControllerTest.java @@ -1,6 +1,13 @@ package me.jweissen.aeticket.controller; +import com.fasterxml.jackson.databind.ObjectMapper; +import me.jweissen.aeticket.dto.request.CartAddRequestDto; +import me.jweissen.aeticket.dto.request.CartEntryRequestDto; +import me.jweissen.aeticket.dto.response.CheckoutResponseDto; import me.jweissen.aeticket.model.Cart; +import me.jweissen.aeticket.model.Role; +import me.jweissen.aeticket.model.User; +import me.jweissen.aeticket.service.AuthService; import me.jweissen.aeticket.service.CartService; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -9,6 +16,13 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; +import java.util.Arrays; + +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; + @WebMvcTest(CartController.class) public class CartControllerTest { @Autowired @@ -16,29 +30,51 @@ public class CartControllerTest { @MockBean private CartService cartService; + @MockBean + private AuthService authService; - /* @Test - void addEntry() { + void addEntry() throws Exception { CartAddRequestDto dto = new CartAddRequestDto( - 999L, - Arrays.asList( - new CartEntryRequestDto(1L, 10), - new CartEntryRequestDto(2L, 10) - ) + 999L, + Arrays.asList( + new CartEntryRequestDto(1L, 10), + new CartEntryRequestDto(2L, 10) + ) ); - Mockito.when(cartService.add()).thenReturn(true); - } - */ - - @Test - void getCartEntries() { - - } - - @Test - void checkout() { Cart cart = new Cart(); - Mockito.when(cartService.checkout(cart)); + User user = User.builder() + .id(1L) + .firstname("jonas") + .lastname("weissensteiner") + .email("my@mail.com") + .password("geheim") + .currentCart(cart) + .role(Role.ADMIN).build(); + Mockito.when(authService.getCurrentUser()).thenReturn(user); + Mockito.when(cartService.add(dto, cart)).thenReturn(true); + final ObjectMapper mapper = new ObjectMapper(); + final String jsonContent = mapper.writeValueAsString(dto); + mockMvc.perform( + post("/cart/add").contentType("application/json").content(jsonContent)).andExpect(status().isNoContent() + ); + } + + @Test + void checkout() throws Exception { + Cart cart = new Cart(); + User user = User.builder() + .id(1L) + .firstname("jonas") + .lastname("weissensteiner") + .email("my@mail.com") + .password("geheim") + .currentCart(cart) + .role(Role.ADMIN).build(); + Mockito.when(authService.getCurrentUser()).thenReturn(user); + Mockito.when(cartService.checkout(cart)).thenReturn(new CheckoutResponseDto(169.99)); + mockMvc.perform( + get("/cart/checkout")).andExpect(jsonPath("$.price").value(169.99) + ); } } diff --git a/src/test/java/me/jweissen/aeticket/service/AuthServiceTest.java b/src/test/java/me/jweissen/aeticket/service/AuthServiceTest.java new file mode 100644 index 0000000..a7c3951 --- /dev/null +++ b/src/test/java/me/jweissen/aeticket/service/AuthServiceTest.java @@ -0,0 +1,45 @@ +package me.jweissen.aeticket.service; + +import me.jweissen.aeticket.model.Role; +import me.jweissen.aeticket.model.User; +import me.jweissen.aeticket.repository.UserRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +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.boot.test.mock.mockito.MockBean; + +import java.util.Date; +import java.util.Optional; + +@SpringBootTest +@AutoConfigureMockMvc +public class AuthServiceTest { + @MockBean + private UserRepository userRepository; + + @Autowired + private JwtService jwtService; + @Autowired + private AuthService authService; + + @Test + void authenticate() { + String token = jwtService.generateToken(1L); + User user = User.builder() + .id(1L) + .firstname("jonas") + .lastname("weissensteiner") + .email("my@mail.com") + .password("geheim") + .token(token) + .tokenValidUntil(new Date(System.currentTimeMillis() + 1000L * 60 * 60)) + .role(Role.ADMIN).build(); + Optional userOptional = Optional.of(user); + Mockito.when(userRepository.findById(1L)).thenReturn(userOptional); + + Assertions.assertEquals(user, authService.authenticate(token).get()); + } +} diff --git a/src/test/java/me/jweissen/aeticket/service/CartServiceTest.java b/src/test/java/me/jweissen/aeticket/service/CartServiceTest.java new file mode 100644 index 0000000..b616e45 --- /dev/null +++ b/src/test/java/me/jweissen/aeticket/service/CartServiceTest.java @@ -0,0 +1,50 @@ +package me.jweissen.aeticket.service; + +import me.jweissen.aeticket.dto.request.CartAddRequestDto; +import me.jweissen.aeticket.dto.request.CartEntryRequestDto; +import me.jweissen.aeticket.model.*; +import me.jweissen.aeticket.repository.CategoryRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +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.boot.test.mock.mockito.MockBean; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Optional; + +@SpringBootTest +@AutoConfigureMockMvc +public class CartServiceTest { + @MockBean + private CategoryRepository categoryRepository; + + @Autowired + private CartService cartService; + + @Test + public void add() { + CartAddRequestDto dto = new CartAddRequestDto( + 1L, + Arrays.asList( + new CartEntryRequestDto(1L, 10), + new CartEntryRequestDto(2L, 20) + ) + ); + Cart cart = new Cart(); + cart.setCartEntries(new ArrayList<>()); + Category category1 = Category.builder() + .id(1L).name("Cat 1").price(200).stock(100).build(); + Category category2 = Category.builder() + .id(2L).name("Cat 2").price(200).stock(100).build(); + Mockito.when(categoryRepository.findById(1L)).thenReturn(Optional.of(category1)); + Mockito.when(categoryRepository.findById(2L)).thenReturn(Optional.of(category2)); + Mockito.when(categoryRepository.unavailableTickets(category1)).thenReturn(0); + Mockito.when(categoryRepository.unavailableTickets(category2)).thenReturn(0); + + Assertions.assertTrue(cartService.add(dto, cart)); + } +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 9b2cc27..8b2b9c4 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -12,9 +12,6 @@ spring: username: test password: test url: 'jdbc:mysql://localhost:5306/test' -server: - servlet: - context-path: '/api/v1' token: secret: "RATP loves Laravel more than Symfony" validForHours: 24 \ No newline at end of file diff --git a/src/test/resources/data.sql b/src/test/resources/data.sql deleted file mode 100644 index 43c7c68..0000000 --- a/src/test/resources/data.sql +++ /dev/null @@ -1,12 +0,0 @@ -INSERT INTO user (id, email, firstname, lastname, password, role, token, token_valid_until) VALUES - (1, 'admin@email.com', 'Admin', 'Chef', 'geheim', 0, 'token', DATE('2023-12-31')); -INSERT INTO cart (id, checked_out, user_id) VALUES (1, false, 1); -UPDATE user SET current_cart_id = 1 WHERE id = 1; - -INSERT INTO event (id, description, end, name, start) VALUES (1, 'Maturaball der Abteilungen EL, IT, ME, Y', '2023-03-03 06:00:00.000000', 'Maturaball HTL Steyr 2024', '2023-03-02 21:00:00.000000'); -INSERT INTO category (id, name, price, stock, event_id) VALUES (1, 'Normal', 2500, 500, 1); -INSERT INTO category (id, name, price, stock, event_id) VALUES (2, 'Maturanten', 0, 500, 1); -INSERT INTO category (id, name, price, stock, event_id) VALUES (3, 'Prechtl', 5000, 1, 1); - -INSERT INTO cart_entry (id, amount, cart_id, category_id) VALUES (3, 1, 2, 3); -