Dashboard mit Anrufhistorie und Dev-Schalter ergänzt

This commit is contained in:
Sven committed 2026-09-21 10:52:55 +02:00
1 parent afd6d03a71
commit 373081d33d
11 files changed
+713 -144

No files matched your search

@@ -141,6 +141,12 @@ public class ArchiveService {
submit("Anrufdaten", () -> calls.forEach(mongo::save));
}
/** Historie der eingehenden Anrufe, auch aus früheren Browser-Sitzungen. */
public List<StoredCall> incomingCalls() {
return mongo.find(new Query(Criteria.where("event").is("incoming"))
.with(Sort.by(Sort.Direction.DESC, "receivedAt", "id")), StoredCall.class);
}
private void submit(String what, Runnable write) {
worker.execute(() -> {
try {
@@ -5,6 +5,7 @@ import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -37,6 +38,12 @@ public class CallController {
this.archive = archive;
}
/** Eingegangene Anrufe, neueste zuerst; Verbindungs- und Ende-Ereignisse zählen nicht erneut. */
@GetMapping
public List<StoredCall> list() {
return archive.incomingCalls();
}
/** Ein Anruf-Ereignis, wie es das Frontend schickt – Felder wie im CallEvent. */
public record CallEventBody(
Integer line,
@@ -2,10 +2,15 @@ package de.appcreation.swyxweb;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
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.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 org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
@@ -15,6 +20,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import de.appcreation.swyxweb.storage.ArchiveService;
import de.appcreation.swyxweb.storage.StoredCall;
/**
* Der Endpunkt nimmt die Anruf-Ereignisse der Startseite an und bestätigt nur
@@ -31,6 +37,29 @@ class CallControllerTests {
@MockitoBean
ArchiveService archive;
@Test
void returnsArchivedIncomingCallsWithoutAnActiveTrayConnection() throws Exception {
when(archive.incomingCalls()).thenReturn(List.of(new StoredCall(
"call-1", Instant.parse("2026-09-20T08:30:00Z"), 1, "incoming", "incoming",
"Muster GmbH (+493012345)", "+493012345", "Muster GmbH", "klingelt", "LSRinging")));
mvc.perform(get("/api/calls"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(1))
.andExpect(jsonPath("$[0].id").value("call-1"))
.andExpect(jsonPath("$[0].receivedAt").value("2026-09-20T08:30:00Z"))
.andExpect(jsonPath("$[0].peerNumber").value("+493012345"))
.andExpect(jsonPath("$[0].peerName").value("Muster GmbH"));
}
@Test
void returnsEmptyHistoryAsAnEmptyArray() throws Exception {
when(archive.incomingCalls()).thenReturn(List.of());
mvc.perform(get("/api/calls"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(0));
}
@Test
void acceptsEventsAndReturnsCount() throws Exception {
mvc.perform(post("/api/calls")
@@ -0,0 +1,31 @@
package de.appcreation.swyxweb;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import de.appcreation.swyxweb.storage.ArchiveService;
import de.appcreation.swyxweb.storage.StoredCall;
class CallHistoryTests {
@Test
void readsOnlyIncomingEventsInNewestFirstOrder() {
MongoTemplate mongo = mock(MongoTemplate.class);
new ArchiveService(mongo).incomingCalls();
ArgumentCaptor<Query> query = ArgumentCaptor.forClass(Query.class);
verify(mongo).find(query.capture(), eq(StoredCall.class));
// direction=incoming würde auch connected/ended zählen und Anrufe verdreifachen.
assertThat(query.getValue().getQueryObject()).containsOnlyKeys("event")
.containsEntry("event", "incoming");
assertThat(query.getValue().getSortObject()).containsEntry("receivedAt", -1)
.containsEntry("id", -1);
}
}