Skip to content

Commit 7efc2b3

Browse files
committed
feature: Add unit tests for DashboardService and refactor DashboardTeamsDTO #deploy-test-dolly-backend
1 parent 0a5d0c0 commit 7efc2b3

2 files changed

Lines changed: 286 additions & 2 deletions

File tree

apps/dolly-backend/src/main/java/no/nav/dolly/domain/dto/DashboardTeamsDTO.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import java.time.LocalDate;
99
import java.util.List;
10-
import java.util.Set;
1110

1211
@Data
1312
@Builder
@@ -25,6 +24,6 @@ public class DashboardTeamsDTO {
2524
public static class Entry {
2625

2726
private String team;
28-
private Integer antall;
27+
private Integer unikeBrukere;
2928
}
3029
}
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
package no.nav.dolly.service;
2+
3+
import no.nav.dolly.consumer.teamkatalog.TeamkatalogConsumer;
4+
import no.nav.dolly.consumer.teamkatalog.dto.TeamkatalogDTO;
5+
import no.nav.dolly.domain.dto.DashboardTeamsDTO;
6+
import no.nav.dolly.domain.jpa.Bruker;
7+
import no.nav.dolly.domain.projection.BestillingerFragment;
8+
import no.nav.dolly.domain.projection.TeamFragment;
9+
import no.nav.dolly.repository.BestillingRepository;
10+
import no.nav.dolly.repository.BrukerRepository;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.api.extension.ExtendWith;
13+
import org.mockito.InjectMocks;
14+
import org.mockito.Mock;
15+
import org.mockito.junit.jupiter.MockitoExtension;
16+
import reactor.core.publisher.Flux;
17+
import reactor.test.StepVerifier;
18+
19+
import java.time.LocalDate;
20+
import java.util.List;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
import static org.mockito.ArgumentMatchers.anyList;
24+
import static org.mockito.Mockito.when;
25+
26+
@ExtendWith(MockitoExtension.class)
27+
class DashboardServiceTest {
28+
29+
private static final LocalDate DATE_1 = LocalDate.of(2024, 1, 1);
30+
private static final LocalDate DATE_2 = LocalDate.of(2024, 1, 2);
31+
32+
@Mock
33+
private BestillingRepository bestillingRepository;
34+
35+
@Mock
36+
private BrukerRepository brukerRepository;
37+
38+
@Mock
39+
private TeamkatalogConsumer teamkatalogConsumer;
40+
41+
@InjectMocks
42+
private DashboardService dashboardService;
43+
44+
// ── getPersonerStatus ────────────────────────────────────────────────────
45+
46+
@Test
47+
void shouldReturnEmptyWhenNoFragments() {
48+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.empty());
49+
50+
StepVerifier.create(dashboardService.getPersonerStatus())
51+
.verifyComplete();
52+
}
53+
54+
@Test
55+
void shouldSumPersonerTotaltForSingleDate() {
56+
var f1 = fragment(DATE_1, 5L, "NYBESTILLING", "OK", "OK");
57+
var f2 = fragment(DATE_1, 3L, "NYBESTILLING", "OK", "OK");
58+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(f1, f2));
59+
60+
StepVerifier.create(dashboardService.getPersonerStatus())
61+
.assertNext(dto -> {
62+
assertThat(dto.getDato()).isEqualTo(DATE_1);
63+
assertThat(dto.getPersonerTotalt()).isEqualTo(8L);
64+
})
65+
.verifyComplete();
66+
}
67+
68+
@Test
69+
void shouldCountNyeByGjenopprettstatusNYBESTILLING() {
70+
var nybestilling = fragment(DATE_1, 4L, "NYBESTILLING", "OK", "OK");
71+
var gjenoppretting = fragment(DATE_1, 2L, "GJENOPPRETTING", "OK", "OK");
72+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(nybestilling, gjenoppretting));
73+
74+
StepVerifier.create(dashboardService.getPersonerStatus())
75+
.assertNext(dto -> {
76+
assertThat(dto.getNye()).isEqualTo(4L);
77+
assertThat(dto.getGjenopprettede()).isEqualTo(2L);
78+
})
79+
.verifyComplete();
80+
}
81+
82+
@Test
83+
void shouldCountPdlFeilByPdlstatusFEIL() {
84+
var feil = fragment(DATE_1, 3L, "NYBESTILLING", "FEIL", "OK");
85+
var ok = fragment(DATE_1, 2L, "NYBESTILLING", "OK", "OK");
86+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(feil, ok));
87+
88+
StepVerifier.create(dashboardService.getPersonerStatus())
89+
.assertNext(dto -> assertThat(dto.getPdlFeil()).isEqualTo(3L))
90+
.verifyComplete();
91+
}
92+
93+
@Test
94+
void shouldCountAndreFeilByAnnenstatusFEIL() {
95+
var feil = fragment(DATE_1, 7L, "NYBESTILLING", "OK", "FEIL");
96+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(feil));
97+
98+
StepVerifier.create(dashboardService.getPersonerStatus())
99+
.assertNext(dto -> assertThat(dto.getAndreFeil()).isEqualTo(7L))
100+
.verifyComplete();
101+
}
102+
103+
@Test
104+
void shouldGroupFragmentsByDateIntoSeparateDtos() {
105+
var d1 = fragment(DATE_1, 10L, "NYBESTILLING", "OK", "OK");
106+
var d2 = fragment(DATE_2, 5L, "NYBESTILLING", "OK", "OK");
107+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(d1, d2));
108+
109+
StepVerifier.create(dashboardService.getPersonerStatus())
110+
.assertNext(dto -> assertThat(dto.getDato()).isEqualTo(DATE_2))
111+
.assertNext(dto -> assertThat(dto.getDato()).isEqualTo(DATE_1))
112+
.verifyComplete();
113+
}
114+
115+
@Test
116+
void shouldSortPersonerStatusByDateDescending() {
117+
var d1 = fragment(DATE_1, 1L, "NYBESTILLING", "OK", "OK");
118+
var d2 = fragment(DATE_2, 1L, "NYBESTILLING", "OK", "OK");
119+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(d1, d2));
120+
121+
StepVerifier.create(dashboardService.getPersonerStatus())
122+
.assertNext(dto -> assertThat(dto.getDato()).isEqualTo(DATE_2))
123+
.assertNext(dto -> assertThat(dto.getDato()).isEqualTo(DATE_1))
124+
.verifyComplete();
125+
}
126+
127+
@Test
128+
void shouldProduceZeroCounstWhenNoMatchingStatuses() {
129+
var f = fragment(DATE_1, 5L, "UKJENT", "UKJENT", "UKJENT");
130+
when(bestillingRepository.findBestillingerOrderBySistOppdatert()).thenReturn(Flux.just(f));
131+
132+
StepVerifier.create(dashboardService.getPersonerStatus())
133+
.assertNext(dto -> {
134+
assertThat(dto.getNye()).isZero();
135+
assertThat(dto.getGjenopprettede()).isZero();
136+
assertThat(dto.getPdlFeil()).isZero();
137+
assertThat(dto.getAndreFeil()).isZero();
138+
})
139+
.verifyComplete();
140+
}
141+
142+
// ── getTeamsStatus ───────────────────────────────────────────────────────
143+
144+
@Test
145+
void shouldReturnEmptyTeamsWhenNoFragments() {
146+
when(brukerRepository.findAll()).thenReturn(Flux.empty());
147+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert()).thenReturn(Flux.empty());
148+
149+
StepVerifier.create(dashboardService.getTeamsStatus())
150+
.verifyComplete();
151+
}
152+
153+
@Test
154+
void shouldSkipBrukereWithBlankEpost() {
155+
var brukerUtenEpost = Bruker.builder().epost("").build();
156+
var brukerMedEpost = Bruker.builder().epost("user@nav.no").build();
157+
when(brukerRepository.findAll()).thenReturn(Flux.just(brukerUtenEpost, brukerMedEpost));
158+
when(teamkatalogConsumer.getTeamForEpost(List.of("user@nav.no")))
159+
.thenReturn(Flux.just(TeamkatalogDTO.builder()
160+
.email("user@nav.no")
161+
.teamNavn(List.of("Team A"))
162+
.build()));
163+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert())
164+
.thenReturn(Flux.just(teamFragment(DATE_1, "user@nav.no")));
165+
166+
StepVerifier.create(dashboardService.getTeamsStatus())
167+
.assertNext(dto -> {
168+
assertThat(dto.getTeams()).hasSize(1);
169+
assertThat(dto.getTeams().getFirst().getTeam()).isEqualTo("Team A");
170+
})
171+
.verifyComplete();
172+
}
173+
174+
@Test
175+
void shouldAssignIngenTeamWhenEmailNotInTeamkatalog() {
176+
var bruker = Bruker.builder().epost("orphan@nav.no").build();
177+
when(brukerRepository.findAll()).thenReturn(Flux.just(bruker));
178+
when(teamkatalogConsumer.getTeamForEpost(anyList())).thenReturn(Flux.empty());
179+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert())
180+
.thenReturn(Flux.just(teamFragment(DATE_1, "orphan@nav.no")));
181+
182+
StepVerifier.create(dashboardService.getTeamsStatus())
183+
.assertNext(dto -> {
184+
assertThat(dto.getTeams()).hasSize(1);
185+
assertThat(dto.getTeams().getFirst().getTeam()).isEqualTo("Tilhører ikke noe team");
186+
assertThat(dto.getTeams().getFirst().getUnikeBrukere()).isEqualTo(1);
187+
})
188+
.verifyComplete();
189+
}
190+
191+
@Test
192+
void shouldCountUniqueUsersPerTeam() {
193+
var bruker1 = Bruker.builder().epost("a@nav.no").build();
194+
var bruker2 = Bruker.builder().epost("b@nav.no").build();
195+
when(brukerRepository.findAll()).thenReturn(Flux.just(bruker1, bruker2));
196+
when(teamkatalogConsumer.getTeamForEpost(anyList())).thenReturn(Flux.just(
197+
TeamkatalogDTO.builder().email("a@nav.no").teamNavn(List.of("Team X")).build(),
198+
TeamkatalogDTO.builder().email("b@nav.no").teamNavn(List.of("Team X")).build()
199+
));
200+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert())
201+
.thenReturn(Flux.just(
202+
teamFragment(DATE_1, "a@nav.no"),
203+
teamFragment(DATE_1, "a@nav.no"),
204+
teamFragment(DATE_1, "b@nav.no")
205+
));
206+
207+
StepVerifier.create(dashboardService.getTeamsStatus())
208+
.assertNext(dto -> {
209+
assertThat(dto.getTeams()).hasSize(1);
210+
assertThat(dto.getTeams().getFirst().getTeam()).isEqualTo("Team X");
211+
assertThat(dto.getTeams().getFirst().getUnikeBrukere()).isEqualTo(2);
212+
})
213+
.verifyComplete();
214+
}
215+
216+
@Test
217+
void shouldAssignUserToMultipleTeams() {
218+
var bruker = Bruker.builder().epost("multi@nav.no").build();
219+
when(brukerRepository.findAll()).thenReturn(Flux.just(bruker));
220+
when(teamkatalogConsumer.getTeamForEpost(anyList())).thenReturn(Flux.just(
221+
TeamkatalogDTO.builder().email("multi@nav.no").teamNavn(List.of("Team A", "Team B")).build()
222+
));
223+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert())
224+
.thenReturn(Flux.just(teamFragment(DATE_1, "multi@nav.no")));
225+
226+
StepVerifier.create(dashboardService.getTeamsStatus())
227+
.assertNext(dto -> {
228+
var teamNames = dto.getTeams().stream().map(DashboardTeamsDTO.Entry::getTeam).toList();
229+
assertThat(teamNames).containsExactlyInAnyOrder("Team A", "Team B");
230+
})
231+
.verifyComplete();
232+
}
233+
234+
@Test
235+
void shouldGroupTeamFragmentsByDateIntoSeparateDtos() {
236+
when(brukerRepository.findAll()).thenReturn(Flux.empty());
237+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert())
238+
.thenReturn(Flux.just(
239+
teamFragment(DATE_1, "a@nav.no"),
240+
teamFragment(DATE_2, "b@nav.no")
241+
));
242+
243+
StepVerifier.create(dashboardService.getTeamsStatus())
244+
.assertNext(dto -> assertThat(dto.getDato()).isEqualTo(DATE_2))
245+
.assertNext(dto -> assertThat(dto.getDato()).isEqualTo(DATE_1))
246+
.verifyComplete();
247+
}
248+
249+
@Test
250+
void shouldSortTeamsStatusByDateDescending() {
251+
when(brukerRepository.findAll()).thenReturn(Flux.empty());
252+
when(bestillingRepository.findBestillingerForTeamsOrderBySistOppdatert())
253+
.thenReturn(Flux.just(
254+
teamFragment(DATE_1, "x@nav.no"),
255+
teamFragment(DATE_2, "y@nav.no")
256+
));
257+
258+
var results = dashboardService.getTeamsStatus().collectList().block();
259+
assertThat(results).isNotNull();
260+
assertThat(results.get(0).getDato()).isEqualTo(DATE_2);
261+
assertThat(results.get(1).getDato()).isEqualTo(DATE_1);
262+
}
263+
264+
// ── helpers ──────────────────────────────────────────────────────────────
265+
266+
private static BestillingerFragment fragment(LocalDate dato, Long personer,
267+
String gjenopprettstatus,
268+
String pdlstatus,
269+
String annenstatus) {
270+
return BestillingerFragment.builder()
271+
.dato(dato)
272+
.personer(personer)
273+
.gjenopprettstatus(gjenopprettstatus)
274+
.pdlstatus(pdlstatus)
275+
.annenstatus(annenstatus)
276+
.build();
277+
}
278+
279+
private static TeamFragment teamFragment(LocalDate dato, String epost) {
280+
return TeamFragment.builder()
281+
.dato(dato)
282+
.epost(epost)
283+
.build();
284+
}
285+
}

0 commit comments

Comments
 (0)