package jnpf.elnService.cross;
|
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import jnpf.elnEntity.field.ElnFieldDefEntity;
|
import jnpf.elnEntity.field.ElnFieldVersionEntity;
|
import jnpf.elnEntity.template.ElnTemplateBindingEntity;
|
import jnpf.elnEntity.template.ElnTemplateCrossReferenceEntity;
|
import jnpf.elnEntity.template.ElnTemplateForms;
|
import jnpf.elnEntity.template.ElnTemplateVersionEntity;
|
import jnpf.elnEntity.template.ElnTemplateVos;
|
import jnpf.elnMapper.ElnFieldDefMapper;
|
import jnpf.elnMapper.ElnFieldVersionMapper;
|
import jnpf.elnMapper.ElnTemplateBindingMapper;
|
import jnpf.elnMapper.ElnTemplateCrossReferenceMapper;
|
import jnpf.elnMapper.ElnTemplateMapper;
|
import jnpf.elnService.cross.impl.ElnCrossTemplateScalarReferenceServiceImpl;
|
import jnpf.elnService.template.ElnTemplateBindingService;
|
import jnpf.elnService.template.TemplateAnnotationAuthorization;
|
import jnpf.exception.DataException;
|
import org.junit.Test;
|
import org.mockito.ArgumentCaptor;
|
|
import java.lang.reflect.Constructor;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.List;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.fail;
|
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 ElnCrossTemplateScalarReferenceServiceImplTest {
|
|
@Test
|
public void exposesEnabledPublishedSourceTemplatesExceptCurrentTemplate() {
|
Fixture fixture = new Fixture();
|
|
List<ElnTemplateVos.CrossTemplateSourceTemplate> templates =
|
fixture.service.sourceTemplates(authorization());
|
|
assertEquals(1, templates.size());
|
assertEquals("source-template", templates.get(0).getSourceTemplateId());
|
assertEquals("SOURCE-TEMPLATE", templates.get(0).getSourceTemplateCode());
|
}
|
|
@Test
|
public void excludesEveryVersionWithTheCurrentTemplateCode() {
|
Fixture fixture = new Fixture();
|
|
assertTrue(fixture.service.sourceTemplates(authorization()).stream()
|
.noneMatch(item -> "TARGET-TEMPLATE".equals(item.getSourceTemplateCode())));
|
|
when(fixture.templateMapper.selectOne(any(Wrapper.class)))
|
.thenReturn(fixture.sameCodeTemplate);
|
assertTrue(fixture.service.candidates(
|
authorization(), fixture.sameCodeTemplate.getId()).isEmpty());
|
}
|
|
@Test
|
public void exposesOnlyEligibleCandidatesFromSelectedSourceTemplate() {
|
Fixture fixture = new Fixture();
|
|
List<ElnTemplateVos.CrossTemplateScalarCandidate> candidates =
|
fixture.service.candidates(authorization(), "source-template");
|
|
assertEquals(1, candidates.size());
|
assertEquals("source-template", candidates.get(0).getSourceTemplateId());
|
assertEquals("SOURCE-TEMPLATE", candidates.get(0).getSourceTemplateCode());
|
assertEquals("source-field", candidates.get(0).getSourceFieldId());
|
assertEquals("source-version", candidates.get(0).getSourceFieldVersionId());
|
|
fixture.field.setBizEnabled("disabled");
|
assertTrue(fixture.service.candidates(authorization(), "source-template").isEmpty());
|
assertTrue(fixture.service.candidates(authorization(), "other-template").isEmpty());
|
}
|
|
@Test
|
public void reservePinsSourceIdentityAndReturnsStableReadOnlyMarker() {
|
Fixture fixture = new Fixture();
|
ElnTemplateForms.ReserveCrossTemplateScalarBinding form = fixture.form();
|
|
ElnTemplateVos.Binding result = fixture.service.reserve(authorization(), form);
|
|
assertEquals("CROSS_TEMPLATE", result.getValueSource());
|
assertEquals(Boolean.TRUE, result.getReadOnly());
|
ArgumentCaptor<ElnTemplateCrossReferenceEntity> captor =
|
ArgumentCaptor.forClass(ElnTemplateCrossReferenceEntity.class);
|
verify(fixture.referenceMapper).insert(captor.capture());
|
ElnTemplateCrossReferenceEntity rule = captor.getValue();
|
assertEquals("target-binding", rule.getMubanBangdingId());
|
assertEquals("source-template", rule.getLaiyuanMubanId());
|
assertEquals("SOURCE-TEMPLATE", rule.getLaiyuanMubanBianhao());
|
assertEquals("source-field", rule.getLaiyuanZiduanDingyiId());
|
assertEquals("source-version", rule.getLaiyuanZiduanBanbenId());
|
assertEquals("tenant-1", rule.getFTenantId());
|
}
|
|
@Test
|
public void rejectsReusingOperationBindingForAnotherSource() {
|
Fixture fixture = new Fixture();
|
ElnTemplateCrossReferenceEntity existing = new ElnTemplateCrossReferenceEntity();
|
existing.setLaiyuanMubanBianhao("OTHER-TEMPLATE");
|
existing.setLaiyuanZiduanBanbenId("source-version");
|
when(fixture.referenceMapper.selectOne(any(Wrapper.class))).thenReturn(existing);
|
|
expectDataException(() -> fixture.service.reserve(authorization(), fixture.form()), "已用于其他跨模板来源");
|
|
verify(fixture.referenceMapper, never()).insert(any(ElnTemplateCrossReferenceEntity.class));
|
}
|
|
@Test
|
public void rejectsCheckboxGroupBeforeReservingCrossTemplateBinding() {
|
Fixture fixture = new Fixture();
|
ElnTemplateForms.ReserveCrossTemplateScalarBinding form = fixture.form();
|
form.setCheckboxGroupCode("result_choice");
|
|
expectDataException(() -> fixture.service.reserve(authorization(), form),
|
"跨模板只读字段不能加入选择组");
|
|
verify(fixture.bindingService, never()).reservePrimary(any(), any());
|
verify(fixture.referenceMapper, never()).insert(any(ElnTemplateCrossReferenceEntity.class));
|
}
|
|
@Test
|
public void contextDecorationRestoresReadOnlyCrossTemplateIdentity() {
|
Fixture fixture = new Fixture();
|
ElnTemplateVos.Binding binding = new ElnTemplateVos.Binding();
|
binding.setId("target-binding");
|
binding.setStatus("PENDING");
|
ElnTemplateVos.AnnotationContext context = new ElnTemplateVos.AnnotationContext();
|
context.setBindings(Collections.singletonList(binding));
|
ElnTemplateCrossReferenceEntity rule = new ElnTemplateCrossReferenceEntity();
|
rule.setMubanBangdingId("target-binding");
|
when(fixture.referenceMapper.selectList(any(Wrapper.class)))
|
.thenReturn(Collections.singletonList(rule));
|
|
fixture.service.decorate(authorization(), context);
|
|
assertEquals("CROSS_TEMPLATE", binding.getValueSource());
|
assertEquals(Boolean.TRUE, binding.getReadOnly());
|
}
|
|
private static void expectDataException(Action action, String fragment) {
|
try {
|
action.run();
|
fail("expected DataException containing " + fragment);
|
} catch (DataException expected) {
|
assertTrue(expected.getMessage().contains(fragment));
|
}
|
}
|
|
private static TemplateAnnotationAuthorization authorization() {
|
try {
|
Constructor<TemplateAnnotationAuthorization> constructor =
|
TemplateAnnotationAuthorization.class.getDeclaredConstructor(
|
String.class, String.class, String.class, String.class);
|
constructor.setAccessible(true);
|
return constructor.newInstance("tenant-1", "user-1", "target-template", "file-1");
|
} catch (ReflectiveOperationException e) {
|
throw new AssertionError(e);
|
}
|
}
|
|
private interface Action {
|
void run();
|
}
|
|
private static final class Fixture {
|
private final ElnTemplateMapper templateMapper = mock(ElnTemplateMapper.class);
|
private final ElnTemplateBindingMapper bindingMapper = mock(ElnTemplateBindingMapper.class);
|
private final ElnFieldDefMapper fieldMapper = mock(ElnFieldDefMapper.class);
|
private final ElnFieldVersionMapper versionMapper = mock(ElnFieldVersionMapper.class);
|
private final ElnTemplateCrossReferenceMapper referenceMapper =
|
mock(ElnTemplateCrossReferenceMapper.class);
|
private final ElnTemplateBindingService bindingService = mock(ElnTemplateBindingService.class);
|
private final ElnFieldDefEntity field = new ElnFieldDefEntity();
|
private final ElnTemplateVersionEntity sameCodeTemplate = new ElnTemplateVersionEntity();
|
private final ElnCrossTemplateScalarReferenceServiceImpl service;
|
|
private Fixture() {
|
ElnTemplateVersionEntity template = new ElnTemplateVersionEntity();
|
template.setId("source-template");
|
template.setFTenantId("tenant-1");
|
template.setMubanBianhao("SOURCE-TEMPLATE");
|
template.setBizStatus("PUBLISHED");
|
template.setBizEnabled("enabled");
|
template.setFDeleteMark(0);
|
ElnTemplateVersionEntity targetTemplate = new ElnTemplateVersionEntity();
|
targetTemplate.setId("target-template");
|
targetTemplate.setFTenantId("tenant-1");
|
targetTemplate.setMubanBianhao("TARGET-TEMPLATE");
|
targetTemplate.setBizStatus("PUBLISHED");
|
targetTemplate.setBizEnabled("enabled");
|
targetTemplate.setFDeleteMark(0);
|
sameCodeTemplate.setId("same-code-template");
|
sameCodeTemplate.setFTenantId("tenant-1");
|
sameCodeTemplate.setMubanBianhao("TARGET-TEMPLATE");
|
sameCodeTemplate.setBizStatus("PUBLISHED");
|
sameCodeTemplate.setBizEnabled("enabled");
|
sameCodeTemplate.setFDeleteMark(0);
|
when(templateMapper.selectList(any(Wrapper.class)))
|
.thenReturn(Arrays.asList(template, targetTemplate, sameCodeTemplate));
|
when(templateMapper.selectOne(any(Wrapper.class))).thenReturn(template);
|
when(templateMapper.selectById("target-template")).thenReturn(targetTemplate);
|
|
ElnTemplateBindingEntity sourceBinding = new ElnTemplateBindingEntity();
|
sourceBinding.setId("source-binding");
|
sourceBinding.setMubanId("source-template");
|
sourceBinding.setZiduanDingyiId("source-field");
|
sourceBinding.setZiduanBanbenId("source-version");
|
sourceBinding.setBangdingZhuangtai("ACTIVE");
|
sourceBinding.setKongjianJuese("PRIMARY");
|
sourceBinding.setFTenantId("tenant-1");
|
sourceBinding.setFDeleteMark(0);
|
when(bindingMapper.selectList(any(Wrapper.class)))
|
.thenReturn(Collections.singletonList(sourceBinding));
|
|
field.setId("source-field");
|
field.setFTenantId("tenant-1");
|
field.setZiduanBianma("source_text");
|
field.setZuoyongFanwei("GLOBAL");
|
field.setBizEnabled("enabled");
|
field.setFDeleteMark(0);
|
when(fieldMapper.selectById("source-field")).thenReturn(field);
|
|
ElnFieldVersionEntity version = new ElnFieldVersionEntity();
|
version.setId("source-version");
|
version.setFTenantId("tenant-1");
|
version.setZiduanDingyiId("source-field");
|
version.setZiduanMingcheng("来源文本");
|
version.setShujuLeixing("TEXT");
|
version.setBizStatus("PUBLISHED");
|
version.setFDeleteMark(0);
|
when(versionMapper.selectById("source-version")).thenReturn(version);
|
|
ElnTemplateVos.Binding target = new ElnTemplateVos.Binding();
|
target.setId("target-binding");
|
target.setStatus("PENDING");
|
when(bindingService.reservePrimary(any(), any())).thenReturn(target);
|
when(referenceMapper.insert(any(ElnTemplateCrossReferenceEntity.class))).thenReturn(1);
|
service = new ElnCrossTemplateScalarReferenceServiceImpl(
|
templateMapper, bindingMapper, fieldMapper, versionMapper,
|
referenceMapper, bindingService);
|
}
|
|
private ElnTemplateForms.ReserveCrossTemplateScalarBinding form() {
|
ElnTemplateForms.ReserveCrossTemplateScalarBinding form =
|
new ElnTemplateForms.ReserveCrossTemplateScalarBinding();
|
form.setOperationCode("reserve-op");
|
form.setSourceTemplateId("source-template");
|
form.setSourceTemplateCode("SOURCE-TEMPLATE");
|
form.setSourceFieldId("source-field");
|
form.setSourceFieldVersionId("source-version");
|
return form;
|
}
|
}
|
}
|