feat: prepare lingxing browser auth and sku measurement inbox
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package com.baiyue.firstleg.lingxing;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LingxingAuthManagerTest {
|
||||
private final LingxingProviderConfig config = new LingxingProviderConfig(
|
||||
"LINGXING_01", "http://127.0.0.1:9222", true, 172800, 300);
|
||||
|
||||
@Test
|
||||
void concurrentRequestsUseOneBrowserRefresh() {
|
||||
LingxingBrowserSessionReader browser = mock(LingxingBrowserSessionReader.class);
|
||||
LingxingAuthState state = new LingxingAuthState("token", "sid=1", Long.MAX_VALUE, "ua", "browser_session");
|
||||
when(browser.read(config, "https://oms.xlwms.com")).thenAnswer(invocation -> {
|
||||
Thread.sleep(40); return state;
|
||||
});
|
||||
LingxingAuthManager manager = new LingxingAuthManager(browser, Clock.systemUTC(), Runnable::run);
|
||||
|
||||
CompletableFuture<LingxingAuthState> first = manager.getAuthState(config, "https://oms.xlwms.com");
|
||||
CompletableFuture<LingxingAuthState> second = manager.getAuthState(config, "https://oms.xlwms.com");
|
||||
|
||||
assertThat(first.join()).isSameAs(state);
|
||||
assertThat(second.join()).isSameAs(state);
|
||||
verify(browser).read(config, "https://oms.xlwms.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void secondaryVerificationBlocksRefreshUntilCooldownExpires() {
|
||||
LingxingBrowserSessionReader browser = mock(LingxingBrowserSessionReader.class);
|
||||
Clock clock = Clock.fixed(Instant.parse("2026-09-21T12:00:00Z"), ZoneOffset.UTC);
|
||||
LingxingAuthManager manager = new LingxingAuthManager(browser, clock, Runnable::run);
|
||||
manager.markSecondaryVerificationRequired(config.providerKey(), 1800);
|
||||
|
||||
assertThatThrownBy(() -> manager.getAuthState(config, "https://oms.xlwms.com").join())
|
||||
.hasRootCauseInstanceOf(LingxingSecondaryVerificationException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jwtExpiryUsesSafetyWindow() {
|
||||
String token = "eyJhbGciOiJub25lIn0.eyJleHAiOjE3OTAwMDAwMDB9.signature";
|
||||
long expected = 1790000000000L - 300_000L;
|
||||
assertThat(LingxingBrowserSessionReader.expiresAt(token, config)).isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
+37
-1
@@ -119,11 +119,47 @@ class MojiaMeasurementOpenApiServiceTest {
|
||||
assertThat(receipt.getValue().getBoxCode()).isEqualTo("PCHK2608140001#5-1");
|
||||
assertThat(receipt.getValue().getScannedShipmentId()).isNull();
|
||||
assertThat(receipt.getValue().getLengthCm()).isEqualByComparingTo("60.1");
|
||||
assertThat(receipt.getValue().getWeightKg()).isEqualByComparingTo("15.13");
|
||||
assertThat(receipt.getValue().getImageFileId()).isEqualTo(3L);
|
||||
assertThat(receipt.getValue().getStatus()).isEqualTo("UNMATCHED");
|
||||
assertThat(receipt.getValue().getTenantId()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void skuWithoutHashIsAcceptedIntoSkuSyncInboxAndDoesNotEnterCartonFlow() {
|
||||
MeasurementRequestAuthenticator authenticator = mock(MeasurementRequestAuthenticator.class);
|
||||
CartonMeasurementService cartons = mock(CartonMeasurementService.class);
|
||||
MeasurementImageClient images = mock(MeasurementImageClient.class);
|
||||
MojiaMeasurementReceiptRepository receipts = mock(MojiaMeasurementReceiptRepository.class);
|
||||
InboundCartonLabelService labels = mock(InboundCartonLabelService.class);
|
||||
var service = new MojiaMeasurementOpenApiService(authenticator, cartons,
|
||||
new ObjectMapper().findAndRegisterModules(), Validation.buildDefaultValidatorFactory().getValidator(),
|
||||
images, receipts, labels);
|
||||
ReflectionTestUtils.setField(service, "internalToken", "internal-token");
|
||||
MeasurementRequestHeaders headers = new MeasurementRequestHeaders("mojia", null, null, null, null);
|
||||
String requestJson = json().replace("PCHK2608140001#5-1", "SKU-NEW-001");
|
||||
when(authenticator.authenticate("POST", MojiaMeasurementOpenApiService.CALLBACK_PATH,
|
||||
headers, requestJson, false)).thenReturn(new AuthenticatedMeasurementApp(
|
||||
"mojia", 0L, 90001L, Map.of("MJ-01", 30001L)));
|
||||
when(images.uploadReceipt(eq("internal-token"), eq(90001L), eq(0L), any(Long.TYPE), any()))
|
||||
.thenReturn(ApiResponse.success(new MeasurementImageClient.UploadResult(
|
||||
9L, "mojia.jpg", "image/jpeg", 4L, "NOT_REQUIRED", null, null, null, null)));
|
||||
|
||||
UploadResponse result = service.receive(headers, requestJson);
|
||||
|
||||
assertThat(result.accepted()).isTrue();
|
||||
assertThat(result.matched()).isFalse();
|
||||
verify(labels, org.mockito.Mockito.never()).resolvePlatformByBoxCode(any());
|
||||
verify(cartons, org.mockito.Mockito.never()).upsert(any(Long.TYPE), any(Long.TYPE), any());
|
||||
ArgumentCaptor<MojiaMeasurementReceiptEntity> receipt =
|
||||
ArgumentCaptor.forClass(MojiaMeasurementReceiptEntity.class);
|
||||
verify(receipts).insert(receipt.capture());
|
||||
assertThat(receipt.getValue().getMeasurementKind()).isEqualTo("SKU");
|
||||
assertThat(receipt.getValue().getSyncStatus()).isEqualTo("PENDING");
|
||||
assertThat(receipt.getValue().getStatus()).isEqualTo("SKU_PENDING_SYNC");
|
||||
assertThat(receipt.getValue().getBoxCode()).isEqualTo("SKU-NEW-001");
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformMachineCannotWriteAnInboundFromAnotherWarehouse() {
|
||||
MeasurementRequestAuthenticator authenticator = mock(MeasurementRequestAuthenticator.class);
|
||||
@@ -153,7 +189,7 @@ class MojiaMeasurementOpenApiServiceTest {
|
||||
private String json() {
|
||||
return """
|
||||
{"boxCode":"PCHK2608140001#5-1","shipment_id":"FBA19L5KMY2CU000002",
|
||||
"length":60.1,"width":40.2,"height":30.3,
|
||||
"length":60.1,"width":40.2,"height":30.3,"weightKg":15.13,
|
||||
"machineNo":"MJ-01","picture":"data:image/jpeg;base64,/9j/2Q=="}
|
||||
""";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user