package jnpf.dmsService;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import jnpf.dmsEntity.watermark.DmsWatermarkConfigEntity;
|
import jnpf.dmsEntity.watermark.DmsWatermarkPositionEntity;
|
import jnpf.dmsEntity.watermark.form.DmsWatermarkConfigForm;
|
import jnpf.dmsEntity.watermark.form.DmsWatermarkPositionForm;
|
import jnpf.dmsEntity.watermark.form.DmsWatermarkQuery;
|
import jnpf.dmsMapper.DmsWatermarkConfigMapper;
|
import jnpf.dmsMapper.DmsWatermarkPositionMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.base.DictionaryDataApi;
|
import jnpf.base.entity.DictionaryDataEntity;
|
import jnpf.exception.DataException;
|
import org.springframework.dao.DuplicateKeyException;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.apache.ibatis.session.Configuration;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.ArgumentCaptor;
|
import org.mockito.Mock;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
|
import java.math.BigDecimal;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.UUID;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.lenient;
|
|
@ExtendWith(MockitoExtension.class)
|
class DmsWatermarkConfigServiceTest {
|
@Mock private DmsWatermarkConfigMapper configMapper;
|
@Mock private DmsWatermarkPositionMapper positionMapper;
|
@Mock private DmsCurrentIdentity identity;
|
@Mock private DictionaryDataApi dictionaryDataApi;
|
private DmsWatermarkConfigService service;
|
|
@BeforeEach
|
void setUp() {
|
initTable(DmsWatermarkConfigEntity.class);
|
initTable(DmsWatermarkPositionEntity.class);
|
service = new DmsWatermarkConfigService(configMapper, positionMapper, identity, dictionaryDataApi);
|
DictionaryDataEntity entry = new DictionaryDataEntity();
|
entry.setDictionaryTypeId("879384732964547653");
|
entry.setEnCode("RECORD");
|
entry.setEnabledMark(1);
|
lenient().when(dictionaryDataApi.getList("879384732964547653", "true")).thenReturn(List.of(entry));
|
}
|
|
@Test
|
void menuUserCanReadWatermarks() throws Exception {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
DmsWatermarkConfigEntity row = new DmsWatermarkConfigEntity();
|
row.setId(UUID.fromString("0199d0e5-8e70-7000-8000-000000000001"));
|
row.setTenantId("tenant-1");
|
row.setName("下载水印");
|
Page<DmsWatermarkConfigEntity> page = new Page<>(1, 20);
|
page.setRecords(Collections.singletonList(row));
|
page.setTotal(1);
|
when(configMapper.selectPage(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(page);
|
when(configMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(row);
|
when(positionMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(Collections.emptyList());
|
|
DmsWatermarkQuery query = new DmsWatermarkQuery();
|
query.setCurrentPage(1);
|
query.setPageSize(20);
|
assertEquals(1, service.list(query).size());
|
assertEquals(row.getId(), service.detail(row.getId()).getId());
|
assertEquals("LEFT", service.detail(row.getId()).getHorizontalAlign());
|
assertEquals("TOP", service.detail(row.getId()).getVerticalAlign());
|
verify(identity, never()).requirePermissionAdministrator();
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
@Test
|
void menuUserCanManageWatermarks() throws Exception {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.nextId()).thenAnswer(ignored -> UUID.randomUUID());
|
DmsWatermarkConfigEntity existing = new DmsWatermarkConfigEntity();
|
existing.setId(UUID.fromString("0199d0e5-8e70-7000-8000-000000000001"));
|
existing.setTenantId("tenant-1");
|
existing.setRevision(1L);
|
when(configMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(existing);
|
when(configMapper.update(any(DmsWatermarkConfigEntity.class), any(LambdaUpdateWrapper.class))).thenReturn(1);
|
when(positionMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(Collections.emptyList());
|
DmsWatermarkConfigForm form = validForm();
|
form.setRevision(1L);
|
|
service.create(form);
|
assertEquals(existing.getId(), service.update(existing.getId(), form).getId());
|
assertEquals(existing.getId(), service.setEnabled(existing.getId(), 1L, false).getId());
|
assertEquals(existing.getId(), service.delete(existing.getId(), 1L).getId());
|
verify(identity, never()).requirePermissionAdministrator();
|
}
|
|
@Test
|
void createsTiledTextWatermarkWithFullyVisibleOpacityAndFreeTextEnterprise() throws Exception {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.nextId()).thenReturn(
|
UUID.fromString("0199d0e5-8e70-7000-8000-000000000001"),
|
UUID.fromString("0199d0e5-8e70-7000-8000-000000000002"));
|
DmsWatermarkConfigForm form = validForm();
|
form.setOpacity(100);
|
form.setLayoutMode("TILED");
|
form.setRepeatSpacingXMm(new BigDecimal("18"));
|
form.setRepeatSpacingYMm(new BigDecimal("24"));
|
|
service.create(form);
|
verify(configMapper).insertBusinessType("tenant-1",
|
UUID.fromString("0199d0e5-8e70-7000-8000-000000000001"), "RECORD");
|
|
ArgumentCaptor<DmsWatermarkConfigEntity> config = ArgumentCaptor.forClass(DmsWatermarkConfigEntity.class);
|
verify(configMapper).insert(config.capture());
|
assertEquals(100, config.getValue().getOpacity());
|
assertEquals("LEFT", config.getValue().getHorizontalAlign());
|
assertEquals("TOP", config.getValue().getVerticalAlign());
|
assertEquals("ALL", config.getValue().getVersionScope());
|
assertEquals("广东丹霞生物制药有限公司", config.getValue().getEnterpriseId());
|
assertEquals("广东丹霞生物制药有限公司", config.getValue().getEnterpriseName());
|
assertEquals(Boolean.TRUE, config.getValue().getLoadDownload());
|
assertEquals(Boolean.TRUE, config.getValue().getLoadPrint());
|
ArgumentCaptor<DmsWatermarkPositionEntity> position = ArgumentCaptor.forClass(DmsWatermarkPositionEntity.class);
|
verify(positionMapper).insert(position.capture());
|
assertEquals("A4", position.getValue().getPaperType());
|
assertEquals(new BigDecimal("210"), position.getValue().getPaperWidthMm());
|
assertEquals(new BigDecimal("297"), position.getValue().getPaperHeightMm());
|
assertEquals(new BigDecimal("65"), position.getValue().getPortraitXMm());
|
assertEquals(new BigDecimal("138"), position.getValue().getPortraitYMm());
|
assertEquals(new BigDecimal("108"), position.getValue().getLandscapeXMm());
|
assertEquals(new BigDecimal("95"), position.getValue().getLandscapeYMm());
|
}
|
|
@Test
|
void createsBarcodeWatermarkWithTextDisplayEnabled() throws Exception {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.nextId()).thenReturn(
|
UUID.fromString("0199d0e5-8e70-7000-8000-000000000001"),
|
UUID.fromString("0199d0e5-8e70-7000-8000-000000000002"));
|
DmsWatermarkConfigForm form = validForm();
|
form.setWatermarkType("BARCODE");
|
form.setBarcodeFormat("QR_CODE");
|
form.setShowBarcodeText(true);
|
|
service.create(form);
|
|
ArgumentCaptor<DmsWatermarkConfigEntity> config = ArgumentCaptor.forClass(DmsWatermarkConfigEntity.class);
|
verify(configMapper).insert(config.capture());
|
assertEquals(Boolean.TRUE, config.getValue().getShowBarcodeText());
|
}
|
|
@Test
|
void customBarcodeAlwaysPersistsItsVisibleTextOption() throws Exception {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.nextId()).thenAnswer(ignored -> UUID.randomUUID());
|
DmsWatermarkConfigForm form = validForm();
|
form.setWatermarkType("BARCODE");
|
form.setBarcodeFormat("QR_CODE");
|
form.setContentTemplate(jnpf.dmsEntity.watermark.DmsWatermarkParameters.CUSTOM_BARCODE_TEMPLATE);
|
form.setShowBarcodeText(false);
|
service.create(form);
|
ArgumentCaptor<DmsWatermarkConfigEntity> config = ArgumentCaptor.forClass(DmsWatermarkConfigEntity.class);
|
verify(configMapper).insert(config.capture());
|
assertEquals(Boolean.TRUE, config.getValue().getShowBarcodeText());
|
assertEquals(form.getContentTemplate(), config.getValue().getContentTemplate());
|
}
|
|
@Test
|
void customPlaceholderCannotBeMixedWithTemplatesOrUsedForTextWatermarks() {
|
DmsWatermarkConfigForm form = validForm();
|
form.setContentTemplate(jnpf.dmsEntity.watermark.DmsWatermarkParameters.CUSTOM_BARCODE_TEMPLATE);
|
assertThrows(DataException.class, () -> service.create(form));
|
form.setWatermarkType("BARCODE");
|
form.setBarcodeFormat("QR_CODE");
|
form.setContentTemplate("prefix" + form.getContentTemplate());
|
assertThrows(DataException.class, () -> service.create(form));
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
@Test
|
void rejectsConfigurationWithoutLoadSceneBeforePersistence() {
|
DmsWatermarkConfigForm form = validForm();
|
form.setLoadScenes(Collections.emptyList());
|
|
DataException error = assertThrows(DataException.class, () -> service.create(form));
|
|
assertEquals("至少选择一个水印加载场景", error.getMessage());
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
@Test
|
void rejectsConfigurationWithoutBusinessType() {
|
DmsWatermarkConfigForm form = validForm();
|
form.setWatermarkBusinessTypes(Collections.emptyList());
|
assertEquals("水印业务配置必须选择 1 到 50 项",
|
assertThrows(DataException.class, () -> service.create(form)).getMessage());
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
@Test
|
void rejectsLandscapeCoordinateOutsideRotatedPage() {
|
DmsWatermarkConfigForm form = validForm();
|
form.getPositions().get(0).setLandscapeYMm(new BigDecimal("211"));
|
|
DataException error = assertThrows(DataException.class, () -> service.create(form));
|
|
assertEquals("横向纵坐标超出允许范围", error.getMessage());
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
@Test
|
void rejectsDuplicateNameWhenCreating() {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(configMapper.selectCount(any(LambdaQueryWrapper.class))).thenReturn(1L);
|
|
DataException error = assertThrows(DataException.class, () -> service.create(validForm()));
|
|
assertEquals("已存在同名水印,请更换名称", error.getMessage());
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
@Test
|
void rejectsDuplicateNameWhenEditing() {
|
UUID id = UUID.randomUUID();
|
DmsWatermarkConfigEntity existing = new DmsWatermarkConfigEntity();
|
existing.setId(id);
|
existing.setRevision(1L);
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(configMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(existing);
|
when(configMapper.selectCount(any(LambdaQueryWrapper.class))).thenReturn(1L);
|
DmsWatermarkConfigForm form = validForm();
|
form.setRevision(1L);
|
|
DataException error = assertThrows(DataException.class, () -> service.update(id, form));
|
|
assertEquals("已存在同名水印,请更换名称", error.getMessage());
|
ArgumentCaptor<LambdaQueryWrapper<DmsWatermarkConfigEntity>> query = ArgumentCaptor.forClass(LambdaQueryWrapper.class);
|
verify(configMapper).selectCount(query.capture());
|
org.junit.jupiter.api.Assertions.assertTrue(query.getValue().getSqlSegment().contains("<>"));
|
verify(configMapper, never()).update(any(DmsWatermarkConfigEntity.class), any(LambdaUpdateWrapper.class));
|
}
|
|
@Test
|
void reportsConcurrentDuplicateNameOnInsert() {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.nextId()).thenReturn(UUID.randomUUID());
|
when(configMapper.insert(any(DmsWatermarkConfigEntity.class))).thenThrow(
|
new DuplicateKeyException("uq_dms_watermark_configs_active_name"));
|
|
DataException error = assertThrows(DataException.class, () -> service.create(validForm()));
|
|
assertEquals("已存在同名水印,请更换名称", error.getMessage());
|
}
|
|
@Test
|
void reportsConcurrentDuplicateNameOnUpdate() {
|
UUID id = UUID.randomUUID();
|
DmsWatermarkConfigEntity existing = new DmsWatermarkConfigEntity();
|
existing.setId(id);
|
existing.setRevision(1L);
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(existing);
|
when(configMapper.update(any(DmsWatermarkConfigEntity.class), any(LambdaUpdateWrapper.class))).thenThrow(
|
new DuplicateKeyException("uq_dms_watermark_configs_active_name"));
|
DmsWatermarkConfigForm form = validForm();
|
form.setRevision(1L);
|
|
DataException error = assertThrows(DataException.class, () -> service.update(id, form));
|
|
assertEquals("已存在同名水印,请更换名称", error.getMessage());
|
}
|
|
@Test
|
void persistsAndReturnsAlignmentOnCreateAndUpdate() throws Exception {
|
when(identity.tenantId()).thenReturn("tenant-1");
|
when(identity.userId()).thenReturn("user-1");
|
when(configMapper.nextId()).thenAnswer(ignored -> UUID.randomUUID());
|
when(positionMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(Collections.emptyList());
|
DmsWatermarkConfigEntity existing = new DmsWatermarkConfigEntity();
|
existing.setId(UUID.randomUUID());
|
existing.setRevision(1L);
|
when(configMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(existing);
|
when(configMapper.update(any(DmsWatermarkConfigEntity.class), any(LambdaUpdateWrapper.class))).thenReturn(1);
|
DmsWatermarkConfigForm form = validForm();
|
form.setHorizontalAlign("center");
|
form.setVerticalAlign("bottom");
|
form.setRevision(1L);
|
|
var created = service.create(form);
|
var updated = service.update(existing.getId(), form);
|
assertEquals("CENTER", created.getHorizontalAlign());
|
assertEquals("BOTTOM", updated.getVerticalAlign());
|
ArgumentCaptor<DmsWatermarkConfigEntity> saved = ArgumentCaptor.forClass(DmsWatermarkConfigEntity.class);
|
verify(configMapper).insert(saved.capture());
|
assertEquals("CENTER", saved.getValue().getHorizontalAlign());
|
assertEquals("BOTTOM", saved.getValue().getVerticalAlign());
|
verify(configMapper).update(saved.capture(), any(LambdaUpdateWrapper.class));
|
assertEquals("CENTER", saved.getValue().getHorizontalAlign());
|
assertEquals("BOTTOM", saved.getValue().getVerticalAlign());
|
}
|
|
@Test
|
void rejectsUnknownAlignmentBeforePersistence() {
|
DmsWatermarkConfigForm form = validForm();
|
form.setHorizontalAlign("JUSTIFY");
|
assertEquals("水平对齐取值无效", assertThrows(DataException.class, () -> service.create(form)).getMessage());
|
form.setHorizontalAlign("LEFT");
|
form.setVerticalAlign("CENTER");
|
assertEquals("垂直对齐取值无效", assertThrows(DataException.class, () -> service.create(form)).getMessage());
|
verify(configMapper, never()).insert(any(DmsWatermarkConfigEntity.class));
|
}
|
|
private DmsWatermarkConfigForm validForm() {
|
DmsWatermarkPositionForm position = new DmsWatermarkPositionForm();
|
position.setPaperType("A4");
|
position.setPaperWidthMm(new BigDecimal("210"));
|
position.setPaperHeightMm(new BigDecimal("297"));
|
position.setPortraitXMm(new BigDecimal("65"));
|
position.setPortraitYMm(new BigDecimal("138"));
|
position.setLandscapeXMm(new BigDecimal("108"));
|
position.setLandscapeYMm(new BigDecimal("95"));
|
DmsWatermarkConfigForm form = new DmsWatermarkConfigForm();
|
form.setName("下载水印");
|
form.setWatermarkType("TEXT");
|
form.setVersionScope("ALL");
|
form.setLoadScenes(Arrays.asList("DOWNLOAD", "PRINT"));
|
form.setWatermarkBusinessTypes(List.of("RECORD"));
|
form.setEnabled(true);
|
form.setEnterpriseName("广东丹霞生物制药有限公司");
|
form.setContentTemplate("下载人:{/CUN}");
|
form.setFontFamily("SimHei");
|
form.setFontColor("#666666");
|
form.setFontSize(24);
|
form.setRotationAngle(-30);
|
form.setOpacity(30);
|
form.setLayoutMode("POSITION");
|
form.setMarkWidthMm(new BigDecimal("80"));
|
form.setMarkHeightMm(new BigDecimal("20"));
|
form.setPositions(Collections.singletonList(position));
|
return form;
|
}
|
|
private void initTable(Class<?> type) {
|
if (TableInfoHelper.getTableInfo(type) == null) {
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), ""), type);
|
}
|
}
|
}
|