package com.baiyue.integration.provider;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
class EvergreenCarrierScheduleProviderAdapterTest {
@Test
void addingThenRevisingEstimateLeavesActualEventStableAndAuditsWholeHtml() throws Exception {
var adapter = new EvergreenCarrierScheduleProviderAdapter(mock(EvergreenTrackingClient.class));
var time = LocalDateTime.of(2026, 8, 21, 12, 0);
var first = adapter.observations("EGSU9319340", new EvergreenTrackingClient.TrackingResponse(CONTAINER_HTML, "", "0000", CONTAINER_HTML), time);
String raw = CONTAINER_HTML + BILL_HTML;
var second = adapter.observations("EGSU9319340", new EvergreenTrackingClient.TrackingResponse(CONTAINER_HTML, BILL_HTML, "0000", raw), time.plusHours(3));
CarrierResponseAuditAssertions.stableSharedFacts(first, second, CONTAINER_HTML, raw);
String revised = BILL_HTML.replace("AUG-07", "AUG-08");
var third = adapter.observations("EGSU9319340", new EvergreenTrackingClient.TrackingResponse(CONTAINER_HTML, revised, "0000", CONTAINER_HTML + revised), time.plusHours(6));
CarrierResponseAuditAssertions.stableSharedFacts(second, third, raw, CONTAINER_HTML + revised);
assertThat(first).hasSize(1); assertThat(second).hasSize(2);
}
private static final String CONTAINER_HTML = """
| Method | 地点 | 箱号 | 货柜动态 | 日期 | 柜型 | VGM | 船名航次 |
| CY | NINGBO, CHINA (CN) | EGSU9319340 | Loaded (FCL) on vessel |
AUG-07-2026 | 40HQ | | EVER LOVELY 1232-067E |
| CY | NINGBO, CHINA (CN) | EITU1262610 | Loaded (FCL) on vessel |
AUG-06-2026 | 40HQ | | EVER LOVELY 1232-067E |
""";
private static final String BILL_HTML = """
""";
@Test
void mapsTheExactContainerRowAndPreservesDayPrecisionWithoutUsingObservedAtAsActual() {
var response = new EvergreenTrackingClient.TrackingResponse(CONTAINER_HTML, BILL_HTML, "0000",
CONTAINER_HTML + BILL_HTML);
LocalDateTime queriedAt = LocalDateTime.of(2026, 8, 21, 15, 30);
var values = new EvergreenCarrierScheduleProviderAdapter(mock(EvergreenTrackingClient.class))
.observations("egsu9319340", response, queriedAt);
assertThat(values).hasSize(2);
assertThat(values).extracting(value -> value.observedAt()).containsOnly(queriedAt);
assertThat(values).filteredOn(value -> value.actualAt() != null).singleElement().satisfies(value -> {
assertThat(value.standardNode()).isEqualTo("LOADED_ON_VESSEL");
assertThat(value.actualAt()).isEqualTo(LocalDateTime.of(2026, 8, 7, 0, 0));
assertThat(value.actualAt()).isNotEqualTo(queriedAt);
assertThat(value.locationCode()).isEqualTo("CN");
assertThat(value.locationName()).isEqualTo("NINGBO, CHINA (CN)");
assertThat(value.sourceReference()).contains("DATE:AUG-07-2026", "PRECISION:DAY", "ZONE:Asia/Shanghai")
.doesNotContain("000000000000");
});
assertThat(values).filteredOn(value -> value.estimatedAt() != null).singleElement()
.satisfies(value -> assertThat(value.estimatedAt()).isEqualTo(LocalDateTime.of(2026, 8, 7, 0, 0)));
}
@Test
void secondConfirmedFixtureRowUsesItsOwnDateAndUnknownStatusesStayUnmapped() {
var response = new EvergreenTrackingClient.TrackingResponse(CONTAINER_HTML, "",
"0000", CONTAINER_HTML);
var values = new EvergreenCarrierScheduleProviderAdapter(mock(EvergreenTrackingClient.class))
.observations("EITU1262610", response, LocalDateTime.of(2026, 8, 21, 15, 30));
assertThat(values).singleElement().satisfies(value -> {
assertThat(value.actualAt()).isEqualTo(LocalDateTime.of(2026, 8, 6, 0, 0));
assertThat(value.standardNode()).isEqualTo("LOADED_ON_VESSEL");
});
assertThat(EvergreenCarrierScheduleProviderAdapter.standardNode("Loaded (FCL) on vessel"))
.isEqualTo("LOADED_ON_VESSEL");
assertThat(EvergreenCarrierScheduleProviderAdapter.standardNode("Discharged from vessel")).isNull();
}
@Test
void missingStableHeaderOrExactContainerRowIsNotParsed() {
assertThat(EvergreenCarrierScheduleProviderAdapter.trackingRow(
"| 箱号 | 日期 |
|---|
| EGSU9319340 | AUG-07-2026 |
",
"EGSU9319340")).isNull();
assertThat(EvergreenCarrierScheduleProviderAdapter.trackingRow(CONTAINER_HTML, "OTHER0000000")).isNull();
}
}