Skip to content
Snippets Groups Projects
Commit c8b41af4 authored by Jens Christian Aanestad's avatar Jens Christian Aanestad
Browse files

Merge branch 'master' into 'feat/endpoint-badges'

# Conflicts:
#   src/main/resources/data-test.sql
parents 43ebd1d5 5776aae3
No related branches found
No related tags found
1 merge request!74Feat/endpoint badges
Pipeline #282199 canceled
Showing
with 558 additions and 8 deletions
package no.ntnu.idi.stud.savingsapp.controller.item;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import no.ntnu.idi.stud.savingsapp.dto.store.InventoryDTO;
import no.ntnu.idi.stud.savingsapp.dto.store.ItemDTO;
import no.ntnu.idi.stud.savingsapp.model.store.Item;
import no.ntnu.idi.stud.savingsapp.model.user.User;
import no.ntnu.idi.stud.savingsapp.security.AuthIdentity;
import no.ntnu.idi.stud.savingsapp.service.ItemService;
import no.ntnu.idi.stud.savingsapp.service.UserService;
import java.util.ArrayList;
import java.util.List;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* Controller handling item related requests.
*/
@CrossOrigin
@RestController
@Validated
@RequestMapping("/api/item")
@EnableAutoConfiguration
@Tag(name = "Item", description = "Endpoints for managing store and user inventory.")
public class ItemController {
@Autowired
private ItemService itemService;
@Autowired
private UserService userService;
@Autowired
private ModelMapper modelMapper;
@Operation(summary = "Get available store items", description = "Retrieves all items available in the store and a flag indicating whether the user has purchased each item.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "List of store items fetched successfully")
})
@GetMapping("/store")
public ResponseEntity<List<ItemDTO>> getStore(@AuthenticationPrincipal AuthIdentity identity) {
List<Item> store = itemService.getStore();
List<Item> inventory = itemService.getInventory(identity.getId());
List<ItemDTO> storeDTO = new ArrayList<>();
for(Item item : store) {
ItemDTO itemDTO = modelMapper.map(item, ItemDTO.class);
if(inventory.contains(item)) {
itemDTO.setAlreadyBought(true);
}
storeDTO.add(itemDTO);
}
return ResponseEntity.ok(storeDTO);
}
@Operation(summary = "Get user inventory items", description = "Retrieves a list of all items currently in the inventory of the user.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "List of inventory items fetched successfully")
})
@GetMapping("/inventory")
public ResponseEntity<List<InventoryDTO>> getInventory(@AuthenticationPrincipal AuthIdentity identity) {
List<Item> inventory = itemService.getInventory(identity.getId());
List<InventoryDTO> inventoryDTO = new ArrayList<>();
for(Item item : inventory) {
inventoryDTO.add(modelMapper.map(item, InventoryDTO.class));
}
return ResponseEntity.ok(inventoryDTO);
}
@Operation(summary = "Purchase an item", description = "Performs a purchase of the item by the user. Points will be deducted from the user.")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "Item purchased and added to inventory successfully", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "403", description = "Insufficient points to purchase the item", content = @Content(mediaType = "application/json", schema = @Schema(implementation = String.class)))
})
@PostMapping("/{itemId}")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<String> buyItem(@AuthenticationPrincipal AuthIdentity identity, @PathVariable long itemId) {
Item item = itemService.getItemFromId(itemId);
User user = userService.findById(identity.getId());
boolean purchaseSuccessful = itemService.addItem(user, item);
if (purchaseSuccessful) {
return ResponseEntity.status(HttpStatus.CREATED).build();
} else {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Insufficient points to purchase the item");
}
}
}
package no.ntnu.idi.stud.savingsapp.controller.leaderboard; package no.ntnu.idi.stud.savingsapp.controller.leaderboard;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import no.ntnu.idi.stud.savingsapp.dto.leaderboard.LeaderboardDTO; import no.ntnu.idi.stud.savingsapp.dto.leaderboard.LeaderboardDTO;
import no.ntnu.idi.stud.savingsapp.model.leaderboard.Leaderboard; import no.ntnu.idi.stud.savingsapp.model.leaderboard.Leaderboard;
...@@ -79,4 +82,14 @@ public class LeaderboardController { ...@@ -79,4 +82,14 @@ public class LeaderboardController {
LeaderboardDTO leaderboardDTO = modelMapper.map(leaderboard, LeaderboardDTO.class); LeaderboardDTO leaderboardDTO = modelMapper.map(leaderboard, LeaderboardDTO.class);
return ResponseEntity.ok(leaderboardDTO); return ResponseEntity.ok(leaderboardDTO);
} }
@Operation(summary = "Get sum of total points globally", description = "Get the sum of the total points of all users globally")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Successfully retrieved total points")
})
@GetMapping(value = "/total-points", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Long> getTotalPoints() {
long totalPoints = leaderboardService.getSumTotalEarnedPoints();
return ResponseEntity.ok(totalPoints);
}
} }
package no.ntnu.idi.stud.savingsapp.dto.store;
import java.sql.Timestamp;
import lombok.Data;
@Data
public final class InventoryDTO {
private long id;
private String itemName;
private long imageId;
private Timestamp boughtAt;
}
package no.ntnu.idi.stud.savingsapp.dto.store;
import lombok.Data;
@Data
public class ItemDTO {
private long id;
private String itemName;
private int price;
private long imageId;
private boolean alreadyBought;
}
package no.ntnu.idi.stud.savingsapp.model.user; package no.ntnu.idi.stud.savingsapp.model.store;
import java.sql.Timestamp; import java.sql.Timestamp;
......
package no.ntnu.idi.stud.savingsapp.model.user; package no.ntnu.idi.stud.savingsapp.model.store;
import jakarta.persistence.Embeddable; import jakarta.persistence.Embeddable;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
...@@ -6,6 +6,7 @@ import java.io.Serializable; ...@@ -6,6 +6,7 @@ import java.io.Serializable;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import no.ntnu.idi.stud.savingsapp.model.user.User;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
...@@ -14,7 +15,7 @@ import lombok.NoArgsConstructor; ...@@ -14,7 +15,7 @@ import lombok.NoArgsConstructor;
public class InventoryId implements Serializable { public class InventoryId implements Serializable {
@ManyToOne @ManyToOne
@JoinColumn(name = "item_id") @JoinColumn(name = "item_id")
private Store store; private Item item;
@ManyToOne @ManyToOne
@JoinColumn(name = "user_id") @JoinColumn(name = "user_id")
......
package no.ntnu.idi.stud.savingsapp.model.user; package no.ntnu.idi.stud.savingsapp.model.store;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
...@@ -19,8 +19,8 @@ import no.ntnu.idi.stud.savingsapp.model.image.Image; ...@@ -19,8 +19,8 @@ import no.ntnu.idi.stud.savingsapp.model.image.Image;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Entity @Entity
@Table(name = "store") @Table(name = "item")
public class Store { public class Item {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "item_id") @Column(name = "item_id")
......
...@@ -21,6 +21,8 @@ import lombok.NoArgsConstructor; ...@@ -21,6 +21,8 @@ import lombok.NoArgsConstructor;
import lombok.NonNull; import lombok.NonNull;
import no.ntnu.idi.stud.savingsapp.bank.model.Account; import no.ntnu.idi.stud.savingsapp.bank.model.Account;
import no.ntnu.idi.stud.savingsapp.model.configuration.Configuration; import no.ntnu.idi.stud.savingsapp.model.configuration.Configuration;
import no.ntnu.idi.stud.savingsapp.model.store.Item;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
...@@ -92,7 +94,7 @@ public class User implements UserDetails{ ...@@ -92,7 +94,7 @@ public class User implements UserDetails{
@JoinTable(name = "inventory", @JoinTable(name = "inventory",
joinColumns = @JoinColumn(name = "user_id"), joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "item_id")) inverseJoinColumns = @JoinColumn(name = "item_id"))
private List<Store> items; private List<Item> items;
@OneToOne @OneToOne
@JoinColumn(name = "point_id") @JoinColumn(name = "point_id")
......
package no.ntnu.idi.stud.savingsapp.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import no.ntnu.idi.stud.savingsapp.model.store.Inventory;
import no.ntnu.idi.stud.savingsapp.model.store.InventoryId;
import no.ntnu.idi.stud.savingsapp.model.store.Item;
@Repository
public interface InventoryRepository extends JpaRepository<Inventory, InventoryId> {
@Query(value = "SELECT i.* FROM item i JOIN inventory inv ON i.item_id = inv.item_id WHERE inv.user_id = :userId", nativeQuery = true)
List<Item> getInventory(@Param("userId") Long userId);
}
package no.ntnu.idi.stud.savingsapp.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import no.ntnu.idi.stud.savingsapp.model.store.Item;
@Repository
public interface StoreRepository extends JpaRepository<Item, Long> {
@Query(value = "SELECT i.* FROM item i JOIN inventory inv ON i.item_id = inv.item_id WHERE inv.user_id = :userId", nativeQuery = true)
List<Item> getInventory(@Param("userId") Long userId);
}
...@@ -261,4 +261,15 @@ public interface UserRepository extends JpaRepository<User, Long> { ...@@ -261,4 +261,15 @@ public interface UserRepository extends JpaRepository<User, Long> {
@Modifying @Modifying
@Query("UPDATE User u SET u.subscriptionLevel = :subscriptionLevel WHERE u.id = :userId") @Query("UPDATE User u SET u.subscriptionLevel = :subscriptionLevel WHERE u.id = :userId")
void updateSubscriptionLevel(@Param("userId") Long userId, @Param("subscriptionLevel") SubscriptionLevel subscriptionLevel); void updateSubscriptionLevel(@Param("userId") Long userId, @Param("subscriptionLevel") SubscriptionLevel subscriptionLevel);
@Query(value = "SELECT SUM(total_earned_points) FROM point", nativeQuery = true)
long getSumTotalEarnedPoints();
@Transactional
@Modifying
@Query(value = "UPDATE point p " +
"JOIN user u ON u.point_id = p.point_id " +
"SET p.current_points = p.current_points - :points " +
"WHERE u.user_id = :userId", nativeQuery = true)
void deductPoints(@Param("userId") Long userId, @Param("points") int points);
} }
package no.ntnu.idi.stud.savingsapp.service;
import java.util.List;
import org.springframework.stereotype.Service;
import no.ntnu.idi.stud.savingsapp.model.store.Item;
import no.ntnu.idi.stud.savingsapp.model.user.User;
/**
* Service interface for item-related operations.
*/
@Service
public interface ItemService {
/**
* Retrieves the inventory of items for a specific user.
*
* @param userId the unique identifier of the user whose inventory is to be retrieved
* @return a list of {@link Item} objects representing the user's inventory
*/
List<Item> getInventory(Long userId);
/**
* Retrieves a list of all items available in the store.
*
* @return a list of {@link Item} objects representing all items currently available in the store
*/
List<Item> getStore();
/**
* Retrieves a specific item from the store based on its identifier.
*
* @param itemId the unique identifier of the item to be retrieved
* @return the {@link Item} corresponding to the provided identifier, or null if no such item exists
*/
Item getItemFromId(Long itemId);
/**
* Adds an item to the inventory of a specified user.
*
* @param user the {@link User} object representing the user to whom the item will be added
* @param item the {@link Item} to be added to the user's inventory
*/
Boolean addItem(User user, Item item);
}
...@@ -34,4 +34,12 @@ public interface LeaderboardService { ...@@ -34,4 +34,12 @@ public interface LeaderboardService {
*/ */
Leaderboard getSurrounding(LeaderboardType type, LeaderboardFilter filter, int entryCount, Long userId); Leaderboard getSurrounding(LeaderboardType type, LeaderboardFilter filter, int entryCount, Long userId);
/**
* Get the total sum of the total points of all users.
*
* @return Long
*/
long getSumTotalEarnedPoints();
} }
\ No newline at end of file
...@@ -151,4 +151,22 @@ public interface UserService { ...@@ -151,4 +151,22 @@ public interface UserService {
* @return A list containing all feedback. * @return A list containing all feedback.
*/ */
List<Feedback> getFeedback(); List<Feedback> getFeedback();
/**
* Check if the user has more than or equal to
* amount of current points as points
*
* @param user the user
* @param points the amount of points to compare with
* @return true or false
*/
Boolean hasMorePoints(User user, int points);
/**
* Deduct a number of current points from the user
*
* @param userId The user
* @param points The amount of current points to deduct
*/
void deductPoints(Long userId, int points);
} }
\ No newline at end of file
package no.ntnu.idi.stud.savingsapp.service.impl;
import java.sql.Timestamp;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import no.ntnu.idi.stud.savingsapp.model.store.Inventory;
import no.ntnu.idi.stud.savingsapp.model.store.InventoryId;
import no.ntnu.idi.stud.savingsapp.model.store.Item;
import no.ntnu.idi.stud.savingsapp.model.user.User;
import no.ntnu.idi.stud.savingsapp.repository.InventoryRepository;
import no.ntnu.idi.stud.savingsapp.repository.StoreRepository;
import no.ntnu.idi.stud.savingsapp.service.ItemService;
import no.ntnu.idi.stud.savingsapp.service.UserService;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private InventoryRepository inventoryRepository;
@Autowired
private StoreRepository storeRepository;
@Autowired
private UserService userService;
/**
* Retrieves the inventory of items for a specific user.
*
* @param userId the unique identifier of the user whose inventory is to be retrieved
* @return a list of {@link Item} objects representing the user's inventory
*/
@Override
public List<Item> getInventory(Long userId) {
return storeRepository.getInventory(userId);
}
/**
* Retrieves a list of all items available in the store.
*
* @return a list of {@link Item} objects representing all items currently available in the store
*/
@Override
public List<Item> getStore() {
return storeRepository.findAll();
}
/**
* Retrieves a specific item from the store based on its identifier.
*
* @param itemId the unique identifier of the item to be retrieved
* @return the {@link Item} corresponding to the provided identifier, or null if no such item exists
*/
@Override
public Item getItemFromId(Long itemId) {
Optional<Item> item = storeRepository.findById(itemId);
if(item.isPresent()) {
return item.get();
} else {
return null;
}
}
/**
* Adds an item to the inventory of a specified user.
*
* @param user the {@link User} object representing the user to whom the item will be added
* @param item the {@link Item} to be added to the user's inventory
*/
@Override
public Boolean addItem(User user, Item item) {
InventoryId inventoryId = new InventoryId(item, user);
if(userService.hasMorePoints(user, item.getPrice())) {
inventoryRepository.save(new Inventory(inventoryId, new Timestamp(System.currentTimeMillis())));
userService.deductPoints(user.getId(), item.getPrice());
return true;
} else {
return false;
}
}
}
...@@ -244,4 +244,14 @@ public class LeaderboardServiceImpl implements LeaderboardService { ...@@ -244,4 +244,14 @@ public class LeaderboardServiceImpl implements LeaderboardService {
leaderboard.setEntries(entries); leaderboard.setEntries(entries);
return leaderboard; return leaderboard;
} }
/**
* Get the total sum of the total points of all users.
*
* @return Long
*/
@Override
public long getSumTotalEarnedPoints() {
return userRepository.getSumTotalEarnedPoints();
}
} }
...@@ -376,4 +376,28 @@ public class UserServiceImpl implements UserService { ...@@ -376,4 +376,28 @@ public class UserServiceImpl implements UserService {
public List<Feedback> getFeedback() { public List<Feedback> getFeedback() {
return feedbackRepository.findAll(); return feedbackRepository.findAll();
} }
/**
* Check if the user has more than or equal to
* amount of current points as points
*
* @param user the user
* @param points the amount of points to compare with
* @return true or false
*/
@Override
public Boolean hasMorePoints(User user, int points) {
return user.getPoint().getCurrentPoints() >= points;
}
/**
* Deduct a number of current points from the user
*
* @param userId The user
* @param points The amount of current points to deduct
*/
@Override
public void deductPoints(Long userId, int points) {
userRepository.deductPoints(userId, points);
}
} }
-- Inserting points -- Inserting points
INSERT INTO point (point_id, current_points, total_earned_points) INSERT INTO point (point_id, current_points, total_earned_points)
VALUES VALUES
...@@ -17,6 +18,7 @@ VALUES ...@@ -17,6 +18,7 @@ VALUES
(14, 260, 980), (14, 260, 980),
(15, 280, 1050); (15, 280, 1050);
-- Inserting streaks -- Inserting streaks
INSERT INTO streak (streak_id, current_streak, current_streak_created_at, current_streak_updated_at, highest_streak, highest_streak_created_at, highest_streak_ended_at) INSERT INTO streak (streak_id, current_streak, current_streak_created_at, current_streak_updated_at, highest_streak, highest_streak_created_at, highest_streak_ended_at)
VALUES VALUES
...@@ -36,6 +38,25 @@ VALUES ...@@ -36,6 +38,25 @@ VALUES
(14, 7, '2024-04-29 15:00:00', '2024-04-29 15:00:03', 8, '2024-04-29 15:00:00', '2025-04-29 15:00:00'), (14, 7, '2024-04-29 15:00:00', '2024-04-29 15:00:03', 8, '2024-04-29 15:00:00', '2025-04-29 15:00:00'),
(15, 3, '2024-04-30 17:30:00', '2024-04-30 17:30:03', 4, '2024-04-30 17:30:00', '2025-04-30 17:30:00'); (15, 3, '2024-04-30 17:30:00', '2024-04-30 17:30:03', 4, '2024-04-30 17:30:00', '2025-04-30 17:30:00');
-- Inserting points
INSERT INTO point (point_id, current_points, total_earned_points)
VALUES
(1, 120, 500),
(2, 150, 600),
(3, 200, 700),
(4, 180, 550),
(5, 220, 800),
(6, 160, 530),
(7, 190, 620),
(8, 250, 900),
(9, 170, 480),
(10, 210, 750),
(11, 230, 850),
(12, 270, 1000),
(13, 240, 920),
(14, 260, 980),
(15, 280, 1050);
-- Inserting users (PASSWORD = John1) -- Inserting users (PASSWORD = John1)
INSERT INTO user (user_id, first_name, last_name, password, email, created_at, role, point_id, streak_id) INSERT INTO user (user_id, first_name, last_name, password, email, created_at, role, point_id, streak_id)
VALUES VALUES
...@@ -130,3 +151,20 @@ INSERT INTO badge (badge_id, badge_name, criteria, image_id) VALUES ...@@ -130,3 +151,20 @@ INSERT INTO badge (badge_id, badge_name, criteria, image_id) VALUES
INSERT INTO badge_user (earned_at, user_id, badge_id) VALUES INSERT INTO badge_user (earned_at, user_id, badge_id) VALUES
('2024-05-01 11:13:42.833664', 1, 1), ('2024-05-01 11:13:42.833664', 1, 1),
('2024-05-01 11:13:42.833664', 1, 2); ('2024-05-01 11:13:42.833664', 1, 2);
-- Inserting items
INSERT INTO item (item_id, price, image_id, item_name) VALUES
(1, 100, null, 'Item 1'),
(2, 200, null, 'Item 2'),
(3, 150, null, 'Item 3'),
(4, 300, null, 'Item 4'),
(5, 250, null, 'Item 5');
-- Inserting inventory
INSERT INTO inventory (bought_at, item_id, user_id)
VALUES
('2024-04-16 15:00:00', 1, 1),
('2024-04-17 10:30:00', 2, 2),
('2024-04-18 08:45:00', 3, 3),
('2024-04-19 12:15:00', 4, 4),
('2024-04-20 17:20:00', 5, 5);
package no.ntnu.idi.stud.savingsapp.controller.item;
import no.ntnu.idi.stud.savingsapp.UserUtil;
import no.ntnu.idi.stud.savingsapp.model.user.Role;
import no.ntnu.idi.stud.savingsapp.model.user.User;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.security.test.context.support.WithMockUser;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
public class ItemControllerTest {
@Autowired
private MockMvc mvc;
private User user;
@BeforeEach
public void setup() {
user = new User();
user.setId(3L);
user.setRole(Role.USER);
user.setEmail("testuser1@example.com");
}
@Test
void getInventoryShouldReturnItemWithId3() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/item/inventory")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1)))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(3))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].itemName").value("Item 3"));
}
@Test
@WithMockUser
void getStoreShouldReturnEntireStore() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/item/store")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(5)));
}
@Test
@WithMockUser
void getStoreShouldReturnItem3AsAlreadyBought() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/item/store")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.jsonPath("$[2].alreadyBought").value(true));
}
@Test
@WithMockUser
void buyItemShouldNotWorkIfUserHasTooFewPoints() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/api/item/5")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isForbidden());
}
@Test
@WithMockUser
void buyItemShouldWorkIfUserHasEnough() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/api/item/1")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isCreated());
}
@Test
@WithMockUser
void buyItemShouldAddItemToInventory() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/api/item/1")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isCreated());
mvc.perform(MockMvcRequestBuilders.get("/api/item/inventory")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2)))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].itemName").value("Item 1"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].id").value(3))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].itemName").value("Item 3"));
}
@Test
@WithMockUser
void buyItemShouldBeMarkedAsPurchasedInStore() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/item/store")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$[0].alreadyBought").value(false));
mvc.perform(MockMvcRequestBuilders.post("/api/item/1")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isCreated());
mvc.perform(MockMvcRequestBuilders.get("/api/item/store")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user))))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$[0].alreadyBought").value(true));
}
}
...@@ -2,14 +2,21 @@ package no.ntnu.idi.stud.savingsapp.controller.leaderboard; ...@@ -2,14 +2,21 @@ package no.ntnu.idi.stud.savingsapp.controller.leaderboard;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.transaction.annotation.Transactional;
import static org.mockito.Mockito.when; 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.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
...@@ -25,6 +32,7 @@ import no.ntnu.idi.stud.savingsapp.UserUtil; ...@@ -25,6 +32,7 @@ import no.ntnu.idi.stud.savingsapp.UserUtil;
@SpringBootTest @SpringBootTest
@AutoConfigureMockMvc @AutoConfigureMockMvc
@Transactional
public class LeaderboardControllerTest { public class LeaderboardControllerTest {
@Autowired @Autowired
...@@ -33,6 +41,9 @@ public class LeaderboardControllerTest { ...@@ -33,6 +41,9 @@ public class LeaderboardControllerTest {
@MockBean @MockBean
private LeaderboardService leaderboardService; private LeaderboardService leaderboardService;
@InjectMocks
private LeaderboardController leaderboardController;
private User user1; private User user1;
private User user2; private User user2;
private User user3; private User user3;
...@@ -283,4 +294,14 @@ public class LeaderboardControllerTest { ...@@ -283,4 +294,14 @@ public class LeaderboardControllerTest {
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user1)))) .with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user1))))
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
@Test
void getTotalEarnedPointsReturns5000() throws Exception {
when(leaderboardService.getSumTotalEarnedPoints()).thenReturn(5000L);
mvc.perform(get("/api/leaderboard/total-points")
.with(SecurityMockMvcRequestPostProcessors.authentication(UserUtil.getAuthentication(user1))))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("5000"));
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment