Dev #18
@@ -15,6 +15,7 @@ import org.springframework.web.server.ResponseStatusException;
|
|||||||
|
|
||||||
import de.zendric.app.xpensely_server.model.*;
|
import de.zendric.app.xpensely_server.model.*;
|
||||||
import de.zendric.app.xpensely_server.model.DTO.HistoryPageDto;
|
import de.zendric.app.xpensely_server.model.DTO.HistoryPageDto;
|
||||||
|
import de.zendric.app.xpensely_server.model.DTO.RecentHistoryEntryDto;
|
||||||
import de.zendric.app.xpensely_server.security.AuthenticatedUserResolver;
|
import de.zendric.app.xpensely_server.security.AuthenticatedUserResolver;
|
||||||
import de.zendric.app.xpensely_server.services.CategoryService;
|
import de.zendric.app.xpensely_server.services.CategoryService;
|
||||||
import de.zendric.app.xpensely_server.services.ExpenseListService;
|
import de.zendric.app.xpensely_server.services.ExpenseListService;
|
||||||
@@ -194,6 +195,14 @@ public class ExpenseListController {
|
|||||||
return ResponseEntity.ok(historyService.getHistory(id, page, size));
|
return ResponseEntity.ok(historyService.getHistory(id, page, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/history/recent")
|
||||||
|
public ResponseEntity<List<RecentHistoryEntryDto>> getRecentHistory(
|
||||||
|
@RequestParam(defaultValue = "4") int limit,
|
||||||
|
Authentication authentication) {
|
||||||
|
AppUser user = authenticatedUserResolver.resolveCurrentUser(authentication);
|
||||||
|
return ResponseEntity.ok(historyService.getRecentForUser(user, limit));
|
||||||
|
}
|
||||||
|
|
||||||
private void assertOwner(AppUser authenticated, ExpenseList list) {
|
private void assertOwner(AppUser authenticated, ExpenseList list) {
|
||||||
if (!list.getOwner().getId().equals(authenticated.getId()))
|
if (!list.getOwner().getId().equals(authenticated.getId()))
|
||||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
|
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
|
||||||
|
|||||||
+46
@@ -3,6 +3,7 @@ package de.zendric.app.xpensely_Server.controller;
|
|||||||
import de.zendric.app.xpensely_server.controller.ExpenseListController;
|
import de.zendric.app.xpensely_server.controller.ExpenseListController;
|
||||||
import de.zendric.app.xpensely_server.model.AppUser;
|
import de.zendric.app.xpensely_server.model.AppUser;
|
||||||
import de.zendric.app.xpensely_server.model.DTO.HistoryPageDto;
|
import de.zendric.app.xpensely_server.model.DTO.HistoryPageDto;
|
||||||
|
import de.zendric.app.xpensely_server.model.DTO.RecentHistoryEntryDto;
|
||||||
import de.zendric.app.xpensely_server.model.Expense;
|
import de.zendric.app.xpensely_server.model.Expense;
|
||||||
import de.zendric.app.xpensely_server.model.ExpenseList;
|
import de.zendric.app.xpensely_server.model.ExpenseList;
|
||||||
import de.zendric.app.xpensely_server.security.AuthenticatedUserResolver;
|
import de.zendric.app.xpensely_server.security.AuthenticatedUserResolver;
|
||||||
@@ -370,4 +371,49 @@ class ExpenseListControllerTest {
|
|||||||
mockMvc.perform(get("/api/expenselist/99/history"))
|
mockMvc.perform(get("/api/expenselist/99/history"))
|
||||||
.andExpect(status().isNotFound());
|
.andExpect(status().isNotFound());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Recent history endpoint ---
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getRecentHistory_returnsArrayWithListInfo() throws Exception {
|
||||||
|
AppUser user = new AppUser(); user.setId(1L); user.setUsername("alice");
|
||||||
|
when(authenticatedUserResolver.resolveCurrentUser(any())).thenReturn(user);
|
||||||
|
when(historyService.getRecentForUser(user, 4)).thenReturn(List.of(
|
||||||
|
new RecentHistoryEntryDto("UPDATED", "alice", "Groceries",
|
||||||
|
LocalDateTime.of(2026, 7, 6, 12, 0), 10L, "Trip to Rome")));
|
||||||
|
|
||||||
|
mockMvc.perform(get("/api/expenselist/history/recent"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$[0].type").value("UPDATED"))
|
||||||
|
.andExpect(jsonPath("$[0].actorUsername").value("alice"))
|
||||||
|
.andExpect(jsonPath("$[0].expenseTitle").value("Groceries"))
|
||||||
|
.andExpect(jsonPath("$[0].listId").value(10))
|
||||||
|
.andExpect(jsonPath("$[0].listName").value("Trip to Rome"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getRecentHistory_passesLimitParam() throws Exception {
|
||||||
|
AppUser user = new AppUser(); user.setId(1L);
|
||||||
|
when(authenticatedUserResolver.resolveCurrentUser(any())).thenReturn(user);
|
||||||
|
when(historyService.getRecentForUser(user, 10)).thenReturn(List.of());
|
||||||
|
|
||||||
|
mockMvc.perform(get("/api/expenselist/history/recent").param("limit", "10"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getRecentHistory_doesNotClashWithPerListHistoryRoute() throws Exception {
|
||||||
|
// /api/expenselist/1/history must still hit the per-list handler.
|
||||||
|
AppUser owner = new AppUser(); owner.setId(1L); owner.setUsername("alice");
|
||||||
|
ExpenseList list = new ExpenseList(); list.setId(1L); list.setOwner(owner);
|
||||||
|
when(expenseListService.findById(1L)).thenReturn(Optional.of(list));
|
||||||
|
when(authenticatedUserResolver.resolveCurrentUser(any())).thenReturn(owner);
|
||||||
|
when(historyService.getHistory(1L, 0, 30))
|
||||||
|
.thenReturn(new HistoryPageDto(List.of(), false));
|
||||||
|
|
||||||
|
mockMvc.perform(get("/api/expenselist/1/history"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.entries").isArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user