package jnpf.fileStorage.dms; import jnpf.dmsEntity.preview.enums.DmsPreviewFormat; import jnpf.dmsEntity.preview.model.DmsFilePreviewTicket; import jnpf.dmsEntity.storage.model.DmsPersistentPdfSource; import jnpf.exception.DataException; import jnpf.onlyoffice.DmsPreviewPdfApi; import org.dromara.x.file.storage.core.FileInfo; import org.dromara.x.file.storage.core.FileStorageService; import org.dromara.x.file.storage.core.platform.MinioFileStorage; import org.junit.After; import org.junit.Test; import java.util.Collections; import java.util.UUID; import java.util.concurrent.Executors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class DmsOnlyOfficePreparedFileServiceTest { private final FileStorageService storage = mock(FileStorageService.class); private final DmsPreviewPdfApi previewPdfApi = mock(DmsPreviewPdfApi.class); private final DmsOnlyOfficePreparedFileService service = new DmsOnlyOfficePreparedFileService( storage, previewPdfApi, Executors.newSingleThreadScheduledExecutor(), ignored -> "source-ticket", ignored -> { }); @After public void tearDown() { service.shutdown(); } @Test public void acceptsExplicitPdfPreviewWithoutCustomBarcode() { DmsFilePreviewTicket ticket = validTicket(); ticket.setPreviewFormat(DmsPreviewFormat.PDF); MinioFileStorage minio = mock(MinioFileStorage.class); when(minio.getBucketName()).thenReturn("jnpf-dms"); when(storage.getFileStorageVerify("seaweedfs-1")).thenReturn(minio); when(previewPdfApi.render(any())).thenThrow(new DataException("render-called")); DataException error = assertThrows(DataException.class, () -> service.prepare(ticket)); assertEquals("render-called", error.getMessage()); verify(previewPdfApi).render(any()); } @Test public void usesExistingPersistentPdfWithoutCallingRenderer() { DmsFilePreviewTicket ticket = validTicket(); ticket.setPreviewFormat(DmsPreviewFormat.PDF); DmsPersistentPdfSource pdf = new DmsPersistentPdfSource(); pdf.setObjectKey("dms-derived/pdf/018f0000/result.pdf"); pdf.setSizeBytes(321L); ticket.setPdfSource(pdf); MinioFileStorage minio = mock(MinioFileStorage.class); when(minio.getBucketName()).thenReturn("jnpf-dms"); when(storage.getFileStorageVerify("seaweedfs-1")).thenReturn(minio); when(storage.exists(any(FileInfo.class))).thenReturn(true); DmsFilePreviewTicket prepared = service.prepare(ticket); assertEquals("result.pdf", prepared.getObjectName()); assertEquals("dms-derived/pdf/018f0000/", prepared.getObjectPath()); assertEquals("quality.pdf", prepared.getFileName()); assertEquals(Long.valueOf(321L), prepared.getSizeBytes()); verify(previewPdfApi, never()).render(any()); } @Test public void missingPersistentPdfFallsBackToExistingRenderer() { DmsFilePreviewTicket ticket = validTicket(); ticket.setPreviewFormat(DmsPreviewFormat.PDF); DmsPersistentPdfSource pdf = new DmsPersistentPdfSource(); pdf.setObjectKey("dms-derived/pdf/018f0000/missing.pdf"); pdf.setSizeBytes(321L); pdf.setSourceChecksumSha256("a".repeat(64)); ticket.setPdfSource(pdf); MinioFileStorage minio = mock(MinioFileStorage.class); when(minio.getBucketName()).thenReturn("jnpf-dms"); when(storage.getFileStorageVerify("seaweedfs-1")).thenReturn(minio); when(storage.exists(any(FileInfo.class))).thenReturn(false); when(previewPdfApi.render(any())).thenThrow(new DataException("fallback-render-called")); DmsPersistentPdfRecoveryReporter reporter = mock(DmsPersistentPdfRecoveryReporter.class); DmsOnlyOfficePreparedFileService reportingService = new DmsOnlyOfficePreparedFileService( storage, previewPdfApi, reporter, Executors.newSingleThreadScheduledExecutor(), ignored -> "source-ticket", ignored -> { }); DataException error; try { error = assertThrows(DataException.class, () -> reportingService.prepare(ticket)); } finally { reportingService.shutdown(); } assertEquals("fallback-render-called", error.getMessage()); verify(previewPdfApi).render(any()); verify(reporter).report(ticket, "持久化 PDF 对象不存在"); } @Test public void rejectsSourcePreviewWithoutCustomBarcode() { DmsFilePreviewTicket ticket = validTicket(); assertThrows(DataException.class, () -> service.prepare(ticket)); verify(previewPdfApi, never()).render(any()); } private DmsFilePreviewTicket validTicket() { DmsFilePreviewTicket ticket = new DmsFilePreviewTicket(); ticket.setFileVersionId(UUID.fromString("018f0000-0000-7000-8000-000000000702")); ticket.setTenantId("tenant-1"); ticket.setUserId("user-1"); ticket.setFileName("quality.docx"); ticket.setStoragePlatform("seaweedfs-1"); ticket.setBucketName("jnpf-dms"); ticket.setObjectPath("2026/09/quality/"); ticket.setObjectName("quality.docx"); ticket.setSizeBytes(1024L); ticket.setWatermarks(Collections.emptyList()); ticket.setExpiresAt(System.currentTimeMillis() + 300_000L); return ticket; } }