This commit is contained in:
2026-08-08 14:19:45 +08:00
parent 87c1bfbb71
commit 13a2b90e98
6 changed files with 304 additions and 5 deletions
@@ -1,6 +1,31 @@
package com.baiyue.firstleg.controller;
import org.junit.jupiter.api.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.security.access.prepost.PreAuthorize; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import static org.assertj.core.api.Assertions.assertThat;
import com.baiyue.common.security.AuthenticatedUser;
import com.baiyue.firstleg.dto.TruckAppointmentDtos.ActionRequest;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.RequestHeader;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class TruckAppointmentControllerContractTest {
@Test void exposesDedicatedEndpointAndPermissions() {String p=PlatformTruckAppointmentController.class.getAnnotation(org.springframework.web.bind.annotation.RequestMapping.class).value()[0];assertThat(p).isEqualTo("/api/platform/v1/truck-appointments"); for(String n:new String[]{"page","detail","create","edit","action","reschedule"}) assertThat(java.util.Arrays.stream(PlatformTruckAppointmentController.class.getDeclaredMethods()).anyMatch(m->m.getName().equals(n))).isTrue();}
@Test void schemaHasAggregateTablesAndStates() throws Exception {String s=new ClassPathResource("db/phase3-truck-appointment-schema.sql").getContentAsString(StandardCharsets.UTF_8);assertThat(s).contains("fl_truck_appointment","fl_truck_appointment_history","fl_truck_appointment_attachment","fl_truck_appointment_operation","PENDING_DISPATCH","PICKUP_IN_PROGRESS","ARRIVED_WAREHOUSE","RESCHEDULED");}
@Test void methodsHavePlatformPermissionsAndAuthenticatedScope() {
Map<String,String> expected=Map.of("page","platform:firstleg:truck-appointment:list","detail","platform:firstleg:truck-appointment:view","create","platform:firstleg:truck-appointment:create","edit","platform:firstleg:truck-appointment:edit","action","platform:firstleg:truck-appointment:operate","reschedule","platform:firstleg:truck-appointment:operate");
for (Method m: PlatformTruckAppointmentController.class.getDeclaredMethods()) { if (!expected.containsKey(m.getName())) continue; assertThat(m.getAnnotation(PreAuthorize.class).value()).isEqualTo("hasAuthority('"+expected.get(m.getName())+"')"); assertThat(java.util.Arrays.stream(m.getParameterAnnotations()).anyMatch(a -> java.util.Arrays.stream(a).anyMatch(x -> x.annotationType()==AuthenticationPrincipal.class))).isTrue(); }
}
@Test void actionKeepsOptionalIdempotencyHeaders() throws Exception {
Method action=PlatformTruckAppointmentController.class.getDeclaredMethod("action", AuthenticatedUser.class,long.class,String.class,String.class,String.class,ActionRequest.class);
RequestHeader[] headers=java.util.Arrays.stream(action.getParameterAnnotations()).flatMap(java.util.Arrays::stream).filter(a -> a instanceof RequestHeader).map(a -> (RequestHeader)a).toArray(RequestHeader[]::new);
assertThat(java.util.Arrays.stream(headers).map(RequestHeader::value)).contains("Idempotency-Key","X-Request-Hash"); assertThat(java.util.Arrays.stream(headers).allMatch(h -> !h.required())).isTrue();
assertThat(PlatformTruckAppointmentController.class.getDeclaredMethod("reschedule", AuthenticatedUser.class,long.class,LocalDateTime.class,ActionRequest.class)).isNotNull();
}
}
@@ -14,11 +14,11 @@ class TruckAppointmentMapperContractTest {
assertThat(TruckAppointmentEntity.class.getAnnotation(TableName.class).value()).isEqualTo("fl_truck_appointment");
String page = TruckAppointmentMapper.class.getMethod("page", com.baomidou.mybatisplus.extension.plugins.pagination.Page.class, com.baiyue.firstleg.dto.TruckAppointmentDtos.Query.class).getAnnotation(Select.class).value()[0];
assertThat(page).contains("fl_truck_appointment", "appointment_no", "vehicle_no", "status=#{q.status}", "container_booking_id=#{q.containerBookingId}");
String transition = TruckAppointmentMapper.class.getMethod("transition", long.class, String.class, String.class, int.class).getAnnotation(Update.class).value();
String transition = TruckAppointmentMapper.class.getMethod("transition", long.class, String.class, String.class, int.class).getAnnotation(Update.class).value()[0];
assertThat(transition).contains("status=#{toStatus}", "status=#{fromStatus}", "version=#{version}", "revision=revision+1", "version=version+1");
String reschedule = TruckAppointmentMapper.class.getMethod("reschedule", long.class, java.time.LocalDateTime.class, String.class, int.class).getAnnotation(Update.class).value();
String reschedule = TruckAppointmentMapper.class.getMethod("reschedule", long.class, java.time.LocalDateTime.class, String.class, int.class).getAnnotation(Update.class).value()[0];
assertThat(reschedule).contains("status='RESCHEDULED'", "version=#{version}", "revision=revision+1");
String edit = TruckAppointmentMapper.class.getMethod("updateEdit", TruckAppointmentEntity.class, int.class).getAnnotation(Update.class).value();
String edit = TruckAppointmentMapper.class.getMethod("updateEdit", TruckAppointmentEntity.class, int.class).getAnnotation(Update.class).value()[0];
assertThat(edit).contains("WHERE id=#{e.id} AND version=#{version}", "version=version+1", "revision=revision+1");
}
}