package jnpf.elnService.template;
|
|
import jnpf.elnEntity.field.ElnFieldDefEntity;
|
import jnpf.elnEntity.field.ElnFieldVersionEntity;
|
import jnpf.elnEntity.template.ElnTemplateBindingEntity;
|
import jnpf.elnEntity.template.ElnTemplateVersionEntity;
|
import jnpf.elnEntity.template.ElnTemplateVos;
|
import jnpf.elnService.template.docx.DocxControlSnapshot;
|
import jnpf.elnService.template.impl.ElnTemplateHealthServiceImpl;
|
import jnpf.exception.DataException;
|
import org.junit.Test;
|
|
import java.lang.reflect.Constructor;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.fail;
|
|
public class ElnTemplateHealthServiceImplTest {
|
|
@Test
|
public void reportsMissingRequiredTestResultBindings() {
|
Fixture fixture = new Fixture();
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertCode(report, "TEST_RESULT_BINDING_REQUIRED");
|
assertCode(report, "TEST_CONCLUSION_BINDING_REQUIRED");
|
assertEquals("ERROR", diagnostic(report,
|
"TEST_RESULT_BINDING_REQUIRED").getSeverity());
|
assertEquals("ERROR", diagnostic(report,
|
"TEST_CONCLUSION_BINDING_REQUIRED").getSeverity());
|
}
|
|
@Test
|
public void reportsSingleCheckboxGroupMemberWithDraftAndPublishedSeverity() {
|
Fixture draft = new Fixture();
|
draft.template.setBizStatus("DRAFT");
|
draft.checkboxBinding("passed", "result_choice", "step-a", false);
|
|
ElnTemplateHealthService.HealthDiagnostic warning = diagnostic(
|
draft.service.inspect("template-1"), "CHECKBOX_GROUP_SINGLE_MEMBER");
|
|
assertEquals("WARNING", warning.getSeverity());
|
assertEquals("result_choice", warning.getCheckboxGroupCode());
|
assertEquals(Collections.singletonList("passed"), warning.getBindingIds());
|
assertEquals("passed", warning.getBindingId());
|
assertEquals(Collections.singletonList("LOCATE"), warning.getActions());
|
assertTrue(warning.getMessage().contains("只有一个成员"));
|
|
Fixture published = new Fixture();
|
published.template.setBizStatus("PUBLISHED");
|
published.checkboxBinding("passed", "result_choice", "step-a", false);
|
assertEquals("ERROR", diagnostic(published.service.inspect("template-1"),
|
"CHECKBOX_GROUP_SINGLE_MEMBER").getSeverity());
|
}
|
|
@Test
|
public void acceptsValidCheckboxGroupAndRejectsScopeOrDefaultConflicts() {
|
Fixture valid = new Fixture();
|
valid.template.setBizStatus("DRAFT");
|
valid.checkboxBinding("passed", "result_choice", "step-a", true);
|
valid.checkboxBinding("failed", "result_choice", "step-a", false);
|
assertNoCode(valid.service.inspect("template-1"), "CHECKBOX_GROUP_SINGLE_MEMBER");
|
assertNoCode(valid.service.inspect("template-1"), "CHECKBOX_GROUP_SCOPE_MISMATCH");
|
assertNoCode(valid.service.inspect("template-1"),
|
"CHECKBOX_GROUP_DEFAULT_COUNT_OUT_OF_RANGE");
|
|
Fixture scope = new Fixture();
|
scope.template.setBizStatus("DRAFT");
|
scope.checkboxBinding("passed", "result_choice", "step-a", false);
|
scope.checkboxBinding("failed", "result_choice", "step-b", false);
|
ElnTemplateHealthService.HealthDiagnostic scopeError = diagnostic(
|
scope.service.inspect("template-1"), "CHECKBOX_GROUP_SCOPE_MISMATCH");
|
assertEquals(Arrays.asList("failed", "passed"), scopeError.getBindingIds());
|
assertTrue(scopeError.getMessage().contains("同一步骤"));
|
|
Fixture defaults = new Fixture();
|
defaults.template.setBizStatus("DRAFT");
|
defaults.checkboxBinding("passed", "result_choice", "step-a", true);
|
defaults.checkboxBinding("failed", "result_choice", "step-a", true);
|
ElnTemplateHealthService.HealthDiagnostic defaultError = diagnostic(
|
defaults.service.inspect("template-1"),
|
"CHECKBOX_GROUP_DEFAULT_COUNT_OUT_OF_RANGE");
|
assertEquals("ERROR", defaultError.getSeverity());
|
assertTrue(defaultError.getMessage().contains("默认勾选"));
|
}
|
|
@Test
|
public void reportsMissingAndOrphanSelectionGroupRules() {
|
Fixture missing = new Fixture();
|
missing.checkboxBinding("passed", "result_choice", "step-a", false);
|
missing.checkboxBinding("failed", "result_choice", "step-a", false);
|
missing.checkboxGroups.clear();
|
assertCode(missing.service.inspect("template-1"),
|
"CHECKBOX_GROUP_RULE_MISSING");
|
|
Fixture orphan = new Fixture();
|
orphan.configureCheckboxGroup("orphan", 0, 1);
|
assertCode(orphan.service.inspect("template-1"),
|
"CHECKBOX_GROUP_WITHOUT_MEMBER");
|
}
|
|
@Test
|
public void reportsInvalidBoundsAndMinimumAboveMemberCount() {
|
Fixture invalid = new Fixture();
|
invalid.checkboxBinding("passed", "result_choice", "step-a", false);
|
invalid.checkboxBinding("failed", "result_choice", "step-a", false);
|
invalid.configureCheckboxGroup("result_choice", 3, 2);
|
assertCode(invalid.service.inspect("template-1"),
|
"CHECKBOX_GROUP_RULE_INVALID");
|
|
Fixture tooFewMembers = new Fixture();
|
tooFewMembers.checkboxBinding("passed", "result_choice", "step-a", true);
|
tooFewMembers.checkboxBinding("failed", "result_choice", "step-a", false);
|
tooFewMembers.configureCheckboxGroup("result_choice", 3, null);
|
assertCode(tooFewMembers.service.inspect("template-1"),
|
"CHECKBOX_GROUP_MIN_EXCEEDS_MEMBERS");
|
}
|
|
@Test
|
public void validatesDefaultCheckedCountAgainstArbitraryRuleBounds() {
|
Fixture twoAllowed = new Fixture();
|
twoAllowed.checkboxBinding("passed", "result_choice", "step-a", true);
|
twoAllowed.checkboxBinding("failed", "result_choice", "step-a", true);
|
twoAllowed.configureCheckboxGroup("result_choice", 1, 2);
|
assertNoCode(twoAllowed.service.inspect("template-1"),
|
"CHECKBOX_GROUP_DEFAULT_COUNT_OUT_OF_RANGE");
|
|
Fixture minimumMissing = new Fixture();
|
minimumMissing.checkboxBinding("passed", "result_choice", "step-a", false);
|
minimumMissing.checkboxBinding("failed", "result_choice", "step-a", false);
|
minimumMissing.configureCheckboxGroup("result_choice", 1, null);
|
assertCode(minimumMissing.service.inspect("template-1"),
|
"CHECKBOX_GROUP_DEFAULT_COUNT_OUT_OF_RANGE");
|
}
|
|
@Test
|
public void reportsInvalidCheckboxGroupCodeMemberAndOwnershipWithoutNullFailure() {
|
Fixture fixture = new Fixture();
|
fixture.template.setBizStatus("DRAFT");
|
fixture.checkboxBinding("passed", "含中文", "step-a", false);
|
fixture.checkboxBinding("failed", "含中文", "step-a", false);
|
fixture.bindings.get(0).setKongjianLeixing("TEXT");
|
fixture.bindings.get(1).setZiduanBanbenId("missing-version");
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertCode(report, "CHECKBOX_GROUP_CODE_INVALID");
|
assertCode(report, "CHECKBOX_GROUP_MEMBER_INVALID");
|
}
|
|
@Test
|
public void rejectsMixedAndDifferentRepeatCheckboxGroupScopes() {
|
Fixture mixed = new Fixture();
|
mixed.checkboxBinding("primary", "result_choice", "step-a", false);
|
mixed.repeatCheckboxBinding("repeat", "result_choice", "samples", false);
|
assertCode(mixed.service.inspect("template-1"), "CHECKBOX_GROUP_SCOPE_MISMATCH");
|
|
Fixture differentRepeats = new Fixture();
|
differentRepeats.repeatCheckboxBinding("sample-result", "result_choice",
|
"samples", false);
|
differentRepeats.repeatCheckboxBinding("result-result", "result_choice",
|
"results", false);
|
assertCode(differentRepeats.service.inspect("template-1"),
|
"CHECKBOX_GROUP_SCOPE_MISMATCH");
|
}
|
|
@Test
|
public void doesNotReportCheckboxGroupDiagnosticsForUngroupedCheckboxes() {
|
Fixture fixture = new Fixture();
|
fixture.checkboxBinding("passed", null, "step-a", false);
|
fixture.checkboxBinding("failed", null, "step-a", false);
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertFalse(report.getDiagnostics().stream().anyMatch(item ->
|
item.getCode().startsWith("CHECKBOX_GROUP_")));
|
}
|
|
@Test
|
public void downloadsOnceReconcilesThenReportsAllAuthoritativeDiagnostics() {
|
Fixture fixture = new Fixture();
|
fixture.template.setBizStatus("DRAFT");
|
fixture.addStandardCases();
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertEquals("template-1", report.getTemplateId());
|
assertEquals("template-1.docx", report.getFileId());
|
assertEquals(1, fixture.downloads);
|
assertEquals(1, fixture.reconciliations);
|
assertEquals(1, fixture.bindingReads);
|
for (String code : Arrays.asList("ORPHAN_CONTROL", "MISSING_CONTROL", "DUPLICATE_TAG",
|
"ROLE_MISMATCH", "TYPE_MISMATCH", "CONFIG_MISMATCH",
|
"REFERENCE_WITHOUT_PRIMARY", "FIELD_VERSION_MISMATCH", "FIELD_DISABLED",
|
"FIELD_VERSION_NOT_PUBLISHED",
|
"PENDING_BINDING", "PENDING_CONFIRMATION_REQUIRED")) {
|
assertCode(report, code);
|
}
|
ElnTemplateHealthService.HealthDiagnostic missing = diagnostic(report, "MISSING_CONTROL");
|
assertEquals("missing", missing.getBindingId());
|
assertEquals("缺失字段", missing.getFieldDisplayName());
|
assertEquals(Arrays.asList("REPAIR", "CONFIRM_REMOVE"), missing.getActions());
|
assertEquals(Collections.singletonList("LOCATE"),
|
diagnostic(report, "ORPHAN_CONTROL").getActions());
|
ElnTemplateHealthService.HealthDiagnostic duplicate = diagnostic(report, "DUPLICATE_TAG");
|
assertEquals("duplicate", duplicate.getBindingId());
|
assertEquals("重复字段", duplicate.getFieldDisplayName());
|
assertEquals("word/header1.xml", diagnostic(report, "ORPHAN_CONTROL").getPartName());
|
assertFalse(report.getDiagnostics().stream()
|
.anyMatch(item -> "cancelled".equals(item.getBindingId())));
|
}
|
|
@Test
|
public void publishedTemplateCheckDoesNotReconcileAndOnlyReturnsLocateActions() {
|
Fixture fixture = new Fixture();
|
fixture.template.setBizStatus("PUBLISHED");
|
fixture.addStandardCases();
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertEquals(1, fixture.downloads);
|
assertEquals(0, fixture.reconciliations);
|
assertEquals(1, fixture.bindingReads);
|
assertTrue(diagnostic(report, "MISSING_CONTROL").getActions().isEmpty());
|
assertEquals(Collections.singletonList("LOCATE"),
|
diagnostic(report, "ORPHAN_CONTROL").getActions());
|
assertEquals(Collections.singletonList("LOCATE"),
|
diagnostic(report, "ROLE_MISMATCH").getActions());
|
assertTrue(report.getDiagnostics().stream().allMatch(item ->
|
item.getActions().isEmpty() || Collections.singletonList("LOCATE").equals(item.getActions())));
|
}
|
|
@Test
|
public void failsClosedForAnotherTenantTemplate() {
|
Fixture fixture = new Fixture();
|
fixture.template.setFTenantId("tenant-b");
|
|
try {
|
fixture.service.inspect("template-1");
|
fail("预期拒绝跨租户模板");
|
} catch (DataException expected) {
|
assertFalse(expected.getMessage().isEmpty());
|
}
|
assertEquals(0, fixture.downloads);
|
}
|
|
@Test
|
public void ignoresUnobservableTextConfigAndCanonicalizesDropdownOptions() {
|
Fixture fixture = new Fixture();
|
fixture.field("text-field", "enabled", "text-version");
|
fixture.version("text-version", "text-field", "PUBLISHED", "文本字段",
|
"{\"placeholder\":\"请输入\",\"defaultValue\":\"默认文本\"}");
|
fixture.binding("text", "text-field", "text-version", "eln.field.text",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
fixture.control("eln.field.text", "TEXT", "PRIMARY",
|
Collections.emptyMap(), "word/document.xml");
|
|
fixture.field("dropdown-field", "enabled", "dropdown-version");
|
fixture.version("dropdown-version", "dropdown-field", "PUBLISHED", "下拉字段",
|
dropdownConfigJson("不合格"));
|
fixture.binding("dropdown", "dropdown-field", "dropdown-version",
|
"eln.field.dropdown", "DROPDOWN", "PRIMARY", null, "ACTIVE");
|
Map<String, Object> reordered = new LinkedHashMap<>();
|
reordered.put("FAIL", "不合格");
|
reordered.put("PASS", "合格");
|
fixture.control("eln.field.dropdown", "DROPDOWN", "PRIMARY",
|
reordered, "word/document.xml");
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertNoDiagnostic(report, "CONFIG_MISMATCH", "text");
|
assertNoDiagnostic(report, "CONFIG_MISMATCH", "dropdown");
|
}
|
|
@Test
|
public void reportsObservableDropdownOptionDifference() {
|
Fixture fixture = new Fixture();
|
fixture.field("dropdown-field", "enabled", "dropdown-version");
|
fixture.version("dropdown-version", "dropdown-field", "PUBLISHED", "下拉字段",
|
dropdownConfigJson("不合格"));
|
fixture.binding("dropdown", "dropdown-field", "dropdown-version",
|
"eln.field.dropdown", "DROPDOWN", "PRIMARY", null, "ACTIVE");
|
Map<String, Object> different = new LinkedHashMap<>();
|
different.put("PASS", "合格");
|
different.put("FAIL", "异常");
|
fixture.control("eln.field.dropdown", "DROPDOWN", "PRIMARY",
|
different, "word/document.xml");
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertDiagnostic(report, "CONFIG_MISMATCH", "dropdown");
|
}
|
|
@Test
|
public void missingControlReturnsExpectedVersionAndEmptyDependencies() {
|
Fixture fixture = new Fixture();
|
fixture.field("missing-field", "enabled", "missing-version");
|
fixture.version("missing-version", "missing-field", "PUBLISHED", "缺失字段", null);
|
fixture.binding("missing", "missing-field", "missing-version", "eln.field.missing",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
fixture.bindings.get(0).setFVersion(7);
|
|
ElnTemplateHealthService.HealthDiagnostic missing = diagnostic(
|
fixture.service.inspect("template-1"), "MISSING_CONTROL");
|
|
assertEquals(Integer.valueOf(7), missing.getExpectedVersion());
|
assertNotNull(missing.getDependencies());
|
assertTrue(missing.getDependencies().isEmpty());
|
}
|
|
@Test
|
public void missingPrimaryMergesActiveReferenceAndValidatorDependencies() {
|
Fixture fixture = new Fixture();
|
fixture.field("field-1", "enabled", "version-1");
|
fixture.version("version-1", "field-1", "PUBLISHED", "样品编号", null);
|
fixture.binding("primary", "field-1", "version-1", "eln.field.sample_id",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
fixture.bindings.get(0).setFVersion(9);
|
fixture.binding("reference", "field-1", "version-1", "eln.ref.sample_id.01",
|
"TEXT", "REFERENCE", "primary", "ACTIVE");
|
fixture.control("eln.ref.sample_id.01", "TEXT", "REFERENCE",
|
Collections.emptyMap(), "word/document.xml");
|
ElnTemplateVos.Diagnostic formula = new ElnTemplateVos.Diagnostic();
|
formula.setSeverity("ERROR");
|
formula.setCode("FORMULA_DEPENDENCY");
|
formula.setMessage("公式仍引用该字段");
|
fixture.validatorDiagnostics = Collections.singletonList(formula);
|
|
ElnTemplateHealthService.HealthDiagnostic missing = diagnostic(
|
fixture.service.inspect("template-1"), "MISSING_CONTROL");
|
|
assertEquals(Integer.valueOf(9), missing.getExpectedVersion());
|
assertTrue(missing.getDependencies().stream().anyMatch(item ->
|
"ACTIVE_REFERENCE_DEPENDENCY".equals(item.getCode())
|
&& "reference".equals(item.getBindingId())));
|
assertTrue(missing.getDependencies().stream().anyMatch(item ->
|
"FORMULA_DEPENDENCY".equals(item.getCode())));
|
assertEquals(Collections.singleton("primary"), fixture.validatedRemovalIds);
|
}
|
|
@Test
|
public void acceptsSingleRepeatPrototypeGroupWhenAllColumnsShareOnePhysicalRow() {
|
Fixture fixture = new Fixture();
|
fixture.repeatBinding("repeat-result", "result", "version-result");
|
fixture.repeatControl("eln.repeat.samples.prototype.result", 0, 2, false, false);
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertFalse(report.getDiagnostics().stream().anyMatch(item ->
|
item.getCode().startsWith("REPEAT_")
|
|| item.getCode().startsWith("MULTIPLE_REPEAT_")));
|
}
|
|
@Test
|
public void rejectsNestedMergedOrSplitRepeatPrototypeRows() {
|
Fixture fixture = new Fixture();
|
fixture.repeatBinding("repeat-result", "result", "version-result");
|
fixture.repeatBinding("repeat-unit", "unit", "version-unit");
|
fixture.repeatControl("eln.repeat.samples.prototype.result", 0, 2, true, true);
|
fixture.repeatControl("eln.repeat.samples.prototype.unit", 0, 3, false, false);
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertCode(report, "NESTED_REPEAT_TABLE");
|
assertCode(report, "REPEAT_VERTICAL_MERGE");
|
assertCode(report, "MULTIPLE_REPEAT_PROTOTYPE_ROWS");
|
}
|
|
@Test
|
public void rejectsNestedContentControlsEvenWhenBindingMatches() {
|
Fixture fixture = new Fixture();
|
fixture.field("nested-field", "enabled", "nested-version");
|
fixture.version("nested-version", "nested-field", "PUBLISHED", "嵌套字段", null);
|
fixture.binding("nested", "nested-field", "nested-version", "eln.field.nested",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
fixture.nestedControl("eln.field.nested", "TEXT", "PRIMARY");
|
|
ElnTemplateHealthService.HealthDiagnostic diagnostic = diagnostic(
|
fixture.service.inspect("template-1"), "NESTED_CONTENT_CONTROL");
|
|
assertEquals("nested", diagnostic.getBindingId());
|
assertEquals("ERROR", diagnostic.getSeverity());
|
}
|
|
@Test
|
public void acceptsIndependentRepeatGroupsOnDifferentRows() {
|
Fixture fixture = new Fixture();
|
fixture.repeatBinding("repeat-result", "result", "version-result");
|
fixture.repeatBinding("repeat-sample", "sample", "version-sample");
|
ElnTemplateBindingEntity second = fixture.bindings.get(1);
|
second.setRepeatGroupCode("results");
|
second.setKongjianBiaoqian("eln.repeat.results.prototype.sample");
|
fixture.configureGroup("results");
|
fixture.repeatControl("eln.repeat.samples.prototype.result", 0, 2, false, false);
|
fixture.repeatControl("eln.repeat.results.prototype.sample", 0, 5, false, false);
|
|
ElnTemplateHealthService.HealthReport report = fixture.service.inspect("template-1");
|
|
assertFalse(report.getDiagnostics().stream().anyMatch(item ->
|
"MULTIPLE_REPEAT_GROUPS".equals(item.getCode())
|
|| "OVERLAPPING_REPEAT_GROUPS".equals(item.getCode())));
|
}
|
|
@Test
|
public void rejectsIndependentRepeatGroupsOnSamePhysicalRow() {
|
Fixture fixture = new Fixture();
|
fixture.repeatBinding("repeat-result", "result", "version-result");
|
fixture.repeatBinding("repeat-sample", "sample", "version-sample");
|
ElnTemplateBindingEntity second = fixture.bindings.get(1);
|
second.setRepeatGroupCode("results");
|
second.setKongjianBiaoqian("eln.repeat.results.prototype.sample");
|
fixture.configureGroup("results");
|
fixture.repeatControl("eln.repeat.samples.prototype.result", 0, 2, false, false);
|
fixture.repeatControl("eln.repeat.results.prototype.sample", 0, 2, false, false);
|
|
assertCode(fixture.service.inspect("template-1"), "OVERLAPPING_REPEAT_GROUPS");
|
}
|
|
@Test
|
public void rejectsRepeatBindingsWithoutGroupConfiguration() {
|
Fixture fixture = new Fixture();
|
fixture.repeatBinding("repeat-result", "result", "version-result");
|
fixture.repeatControl("eln.repeat.samples.prototype.result", 0, 2, false, false);
|
fixture.repeatGroups.clear();
|
|
assertCode(fixture.service.inspect("template-1"), "REPEAT_GROUP_CONFIG_MISSING");
|
}
|
|
private static void assertCode(ElnTemplateHealthService.HealthReport report, String code) {
|
diagnostic(report, code);
|
}
|
|
private static void assertNoCode(ElnTemplateHealthService.HealthReport report, String code) {
|
assertFalse("不应存在诊断: " + code,
|
report.getDiagnostics().stream().anyMatch(item -> code.equals(item.getCode())));
|
}
|
|
private static ElnTemplateHealthService.HealthDiagnostic diagnostic(
|
ElnTemplateHealthService.HealthReport report, String code) {
|
return report.getDiagnostics().stream().filter(item -> code.equals(item.getCode()))
|
.findFirst().orElseThrow(() -> new AssertionError("缺少诊断: " + code));
|
}
|
|
private static void assertDiagnostic(ElnTemplateHealthService.HealthReport report,
|
String code, String bindingId) {
|
assertTrue("缺少诊断: " + code + "/" + bindingId,
|
report.getDiagnostics().stream().anyMatch(item -> code.equals(item.getCode())
|
&& bindingId.equals(item.getBindingId())));
|
}
|
|
private static void assertNoDiagnostic(ElnTemplateHealthService.HealthReport report,
|
String code, String bindingId) {
|
assertFalse("不应存在诊断: " + code + "/" + bindingId,
|
report.getDiagnostics().stream().anyMatch(item -> code.equals(item.getCode())
|
&& bindingId.equals(item.getBindingId())));
|
}
|
|
private static String dropdownConfigJson(String failedDisplay) {
|
return "{\"controlType\":\"dropdown\",\"placeholder\":\"请选择\","
|
+ "\"defaultOptionValue\":\"PASS\",\"options\":["
|
+ "{\"display\":\"合格\",\"value\":\"PASS\"},"
|
+ "{\"display\":\"" + failedDisplay + "\",\"value\":\"FAIL\"}]}";
|
}
|
|
private static final class Fixture implements ElnTemplateHealthServiceImpl.Store {
|
private final ElnTemplateVersionEntity template = new ElnTemplateVersionEntity();
|
private final Map<String, ElnFieldDefEntity> fields = new LinkedHashMap<>();
|
private final Map<String, ElnFieldVersionEntity> versions = new LinkedHashMap<>();
|
private final List<ElnTemplateBindingEntity> bindings = new ArrayList<>();
|
private final List<DocxControlSnapshot> controls = new ArrayList<>();
|
private final List<ElnTemplateVos.RepeatGroup> repeatGroups = new ArrayList<>();
|
private final List<ElnTemplateVos.CheckboxGroup> checkboxGroups =
|
new ArrayList<>();
|
private int downloads;
|
private int reconciliations;
|
private int bindingReads;
|
private List<ElnTemplateVos.Diagnostic> validatorDiagnostics = Collections.emptyList();
|
private Set<String> validatedRemovalIds = Collections.emptySet();
|
private final ElnTemplateHealthService service;
|
|
private Fixture() {
|
template.setId("template-1");
|
template.setFTenantId("tenant-a");
|
template.setMubanFile("[{\"fileId\":\"template-1.docx\",\"fileExtension\":\"docx\"}]");
|
template.setFDeleteMark(0);
|
ElnTemplateDocumentEvidence evidence = (tenant, file) -> {
|
downloads++;
|
assertEquals("tenant-a", tenant);
|
assertEquals("template-1.docx", file);
|
return new ArrayList<>(controls);
|
};
|
ElnTemplateHealthServiceImpl.PendingReconciler reconciler =
|
(tenant, templateId, now, snapshots) -> {
|
reconciliations++;
|
ElnTemplateVos.Diagnostic item = new ElnTemplateVos.Diagnostic();
|
item.setSeverity("WARNING");
|
item.setCode("PENDING_CONFIRMATION_REQUIRED");
|
item.setBindingId("pending");
|
item.setControlTag("eln.field.pending");
|
item.setMessage("需要确认");
|
return Collections.singletonList(item);
|
};
|
ElnTemplateBindingDependencyValidator validator =
|
new ElnTemplateBindingDependencyValidator() {
|
@Override
|
public List<ElnTemplateVos.Diagnostic> validateUpgrade(String tenantId,
|
String templateId, Set<String> bindingIds,
|
String targetFieldVersionId) {
|
return Collections.emptyList();
|
}
|
|
@Override
|
public List<ElnTemplateVos.Diagnostic> validateRemoval(String tenantId,
|
String templateId, Set<String> bindingIds) {
|
validatedRemovalIds = bindingIds;
|
return validatorDiagnostics;
|
}
|
|
@Override
|
public List<ElnTemplateVos.Diagnostic> validatePromotion(String tenantId,
|
String templateId, String primaryBindingId,
|
String referenceBindingId) {
|
return Collections.emptyList();
|
}
|
};
|
service = construct(this, evidence, reconciler, () -> "tenant-a",
|
Collections.singletonList(validator), (tenantId, templateId) ->
|
new ArrayList<>(repeatGroups), (tenantId, templateId) ->
|
new ArrayList<>(checkboxGroups));
|
}
|
|
private void addStandardCases() {
|
field("normal-field", "enabled", "normal-version");
|
version("normal-version", "normal-field", "PUBLISHED", "正常字段", null);
|
binding("normal", "normal-field", "normal-version", "eln.field.normal",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.normal", "TEXT", "PRIMARY", null, "word/document.xml");
|
|
field("missing-field", "enabled", "missing-version");
|
version("missing-version", "missing-field", "PUBLISHED", "缺失字段", null);
|
binding("missing", "missing-field", "missing-version", "eln.field.missing",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
|
field("dup-field", "enabled", "dup-version");
|
version("dup-version", "dup-field", "PUBLISHED", "重复字段", null);
|
binding("duplicate", "dup-field", "dup-version", "eln.field.duplicate",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.duplicate", "TEXT", "PRIMARY", null, "word/document.xml");
|
control("eln.field.duplicate", "TEXT", "PRIMARY", null, "word/footer1.xml");
|
|
field("role-field", "enabled", "role-version");
|
version("role-version", "role-field", "PUBLISHED", "角色字段", null);
|
binding("role", "role-field", "role-version", "eln.field.role",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.role", "TEXT", "REFERENCE", null, "word/document.xml");
|
|
field("type-field", "enabled", "type-version");
|
version("type-version", "type-field", "PUBLISHED", "类型字段", null);
|
binding("type", "type-field", "type-version", "eln.field.type",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.type", "DATE", "PRIMARY", null, "word/document.xml");
|
|
field("config-field", "enabled", "config-version");
|
version("config-version", "config-field", "PUBLISHED", "配置字段",
|
dropdownConfigJson("不合格"));
|
binding("config", "config-field", "config-version", "eln.field.config",
|
"DROPDOWN", "PRIMARY", null, "ACTIVE");
|
Map<String, Object> differentOptions = new LinkedHashMap<>();
|
differentOptions.put("PASS", "合格");
|
differentOptions.put("FAIL", "异常");
|
control("eln.field.config", "DROPDOWN", "PRIMARY",
|
differentOptions, "word/document.xml");
|
|
field("ref-field", "enabled", "ref-version");
|
version("ref-version", "ref-field", "PUBLISHED", "引用字段", null);
|
binding("reference", "ref-field", "ref-version", "eln.ref.reference.01",
|
"TEXT", "REFERENCE", "missing-primary", "ACTIVE");
|
control("eln.ref.reference.01", "TEXT", "REFERENCE", null, "word/document.xml");
|
|
field("version-field", "enabled", "wrong-owner-version");
|
version("wrong-owner-version", "another-field", "PUBLISHED", "错误版本", null);
|
binding("version-mismatch", "version-field", "wrong-owner-version",
|
"eln.field.version_mismatch", "TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.version_mismatch", "TEXT", "PRIMARY", null, "word/document.xml");
|
|
field("disabled-field", "disabled", "disabled-version");
|
version("disabled-version", "disabled-field", "PUBLISHED", "停用字段", null);
|
binding("disabled", "disabled-field", "disabled-version", "eln.field.disabled",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.disabled", "TEXT", "PRIMARY", null, "word/document.xml");
|
|
field("draft-field", "enabled", "draft-version");
|
version("draft-version", "draft-field", "DRAFT", "草稿字段", null);
|
binding("draft", "draft-field", "draft-version", "eln.field.draft",
|
"TEXT", "PRIMARY", null, "ACTIVE");
|
control("eln.field.draft", "TEXT", "PRIMARY", null, "word/document.xml");
|
|
field("pending-field", "enabled", "pending-version");
|
version("pending-version", "pending-field", "PUBLISHED", "待确认字段", null);
|
binding("pending", "pending-field", "pending-version", "eln.field.pending",
|
"TEXT", "PRIMARY", null, "PENDING");
|
control("eln.field.pending", "TEXT", "PRIMARY", null, "word/document.xml");
|
|
binding("cancelled", "normal-field", "normal-version", "eln.field.cancelled",
|
"TEXT", "PRIMARY", null, "CANCELLED");
|
control("eln.field.orphan", "TEXT", "PRIMARY", null, "word/header1.xml");
|
}
|
|
private void repeatBinding(String id, String fieldCode, String versionId) {
|
configureGroup("samples");
|
field(id + "-field", "enabled", versionId);
|
version(versionId, id + "-field", "PUBLISHED", fieldCode, null);
|
binding(id, id + "-field", versionId,
|
"eln.repeat.samples.prototype." + fieldCode,
|
"TEXT", "REPEAT", null, "ACTIVE");
|
ElnTemplateBindingEntity item = bindings.get(bindings.size() - 1);
|
item.setZiduanBianma(fieldCode);
|
item.setRepeatGroupCode("samples");
|
item.setRepeatPrototypeRowId("prototype");
|
}
|
|
private void checkboxBinding(String id, String groupCode, String stepId,
|
boolean defaultChecked) {
|
if (groupCode != null && checkboxGroups.stream().noneMatch(
|
item -> groupCode.equals(item.getGroupCode()))) {
|
configureCheckboxGroup(groupCode, 0, 1);
|
}
|
String fieldId = id + "-field";
|
String versionId = id + "-version";
|
field(fieldId, "enabled", versionId);
|
version(versionId, fieldId, "PUBLISHED", id,
|
"{\"defaultChecked\":" + defaultChecked + "}");
|
versions.get(versionId).setShujuLeixing("CHECKBOX");
|
binding(id, fieldId, versionId, "eln.field." + id,
|
"CHECKBOX", "PRIMARY", null, "ACTIVE");
|
ElnTemplateBindingEntity item = bindings.get(bindings.size() - 1);
|
item.setCheckboxGroupCode(groupCode);
|
item.setStepId(stepId);
|
control(item.getKongjianBiaoqian(), "CHECKBOX", "PRIMARY",
|
Collections.singletonMap("defaultChecked", defaultChecked),
|
"word/document.xml");
|
}
|
|
private void repeatCheckboxBinding(String id, String checkboxGroupCode,
|
String repeatGroupCode,
|
boolean defaultChecked) {
|
if (checkboxGroupCode != null && checkboxGroups.stream().noneMatch(
|
item -> checkboxGroupCode.equals(item.getGroupCode()))) {
|
configureCheckboxGroup(checkboxGroupCode, 0, 1);
|
}
|
configureGroup(repeatGroupCode);
|
String fieldId = id + "-field";
|
String versionId = id + "-version";
|
String tag = "eln.repeat." + repeatGroupCode + ".prototype." + id;
|
field(fieldId, "enabled", versionId);
|
version(versionId, fieldId, "PUBLISHED", id,
|
"{\"defaultChecked\":" + defaultChecked + "}");
|
versions.get(versionId).setShujuLeixing("CHECKBOX");
|
binding(id, fieldId, versionId, tag,
|
"CHECKBOX", "REPEAT", null, "ACTIVE");
|
ElnTemplateBindingEntity item = bindings.get(bindings.size() - 1);
|
item.setCheckboxGroupCode(checkboxGroupCode);
|
item.setRepeatGroupCode(repeatGroupCode);
|
item.setRepeatPrototypeRowId("prototype");
|
controls.add(new DocxControlSnapshot(tag, null, null,
|
"CHECKBOX", "REPEAT", "word/document.xml", "OK",
|
Collections.singletonMap("defaultChecked", defaultChecked),
|
null, 0, repeatGroups.size(), false, false));
|
}
|
|
private void configureGroup(String groupCode) {
|
if (repeatGroups.stream().anyMatch(item -> groupCode.equals(item.getGroupCode()))) {
|
return;
|
}
|
ElnTemplateVos.RepeatGroup group = new ElnTemplateVos.RepeatGroup();
|
group.setGroupCode(groupCode);
|
group.setMinRows(0);
|
group.setMaxRows(100);
|
repeatGroups.add(group);
|
}
|
|
private void configureCheckboxGroup(String groupCode, Integer minSelected,
|
Integer maxSelected) {
|
checkboxGroups.removeIf(item -> groupCode.equals(item.getGroupCode()));
|
ElnTemplateVos.CheckboxGroup group = new ElnTemplateVos.CheckboxGroup();
|
group.setGroupCode(groupCode);
|
group.setMinSelected(minSelected);
|
group.setMaxSelected(maxSelected);
|
group.setVersion(0);
|
checkboxGroups.add(group);
|
}
|
|
private void repeatControl(String tag, int tableIndex, int rowIndex,
|
boolean nested, boolean verticalMerge) {
|
controls.add(new DocxControlSnapshot(tag, null, null, "TEXT", "REPEAT",
|
"word/document.xml", "OK", Collections.emptyMap(), null,
|
tableIndex, rowIndex, nested, verticalMerge));
|
}
|
|
private void nestedControl(String tag, String type, String role) {
|
controls.add(new DocxControlSnapshot(tag, null, null, type, role,
|
"word/document.xml", "OK", Collections.emptyMap(), null,
|
null, null, false, false, true));
|
}
|
|
private void field(String id, String enabled, String currentVersion) {
|
ElnFieldDefEntity item = new ElnFieldDefEntity();
|
item.setId(id);
|
item.setFTenantId("tenant-a");
|
item.setBizEnabled(enabled);
|
item.setDangqianZiduanBanbenId(currentVersion);
|
fields.put(id, item);
|
}
|
|
private void version(String id, String fieldId, String status, String name, String config) {
|
ElnFieldVersionEntity item = new ElnFieldVersionEntity();
|
item.setId(id);
|
item.setFTenantId("tenant-a");
|
item.setZiduanDingyiId(fieldId);
|
item.setBizStatus(status);
|
item.setZiduanMingcheng(name);
|
item.setKongjianPeizhi(config);
|
versions.put(id, item);
|
}
|
|
private void binding(String id, String fieldId, String versionId, String tag,
|
String type, String role, String primaryId, String status) {
|
ElnTemplateBindingEntity item = new ElnTemplateBindingEntity();
|
item.setId(id);
|
item.setFTenantId("tenant-a");
|
item.setMubanId("template-1");
|
item.setZiduanDingyiId(fieldId);
|
item.setZiduanBanbenId(versionId);
|
item.setKongjianBiaoqian(tag);
|
item.setKongjianLeixing(type);
|
item.setKongjianJuese(role);
|
item.setYinyongShiliId(primaryId);
|
item.setBangdingZhuangtai(status);
|
bindings.add(item);
|
}
|
|
private void control(String tag, String type, String role, Map<String, Object> config,
|
String part) {
|
controls.add(new DocxControlSnapshot(tag, null, null, type, role, part, "OK", config));
|
}
|
|
@Override
|
public ElnTemplateVersionEntity findTemplate(String tenantId, String templateId) {
|
return tenantId.equals(template.getFTenantId()) && templateId.equals(template.getId())
|
? template : null;
|
}
|
|
@Override
|
public List<ElnTemplateBindingEntity> listBindings(String tenantId, String templateId) {
|
bindingReads++;
|
return new ArrayList<>(bindings);
|
}
|
|
@Override
|
public ElnFieldDefEntity findField(String tenantId, String fieldId) {
|
ElnFieldDefEntity item = fields.get(fieldId);
|
return item != null && tenantId.equals(item.getFTenantId()) ? item : null;
|
}
|
|
@Override
|
public ElnFieldVersionEntity findFieldVersion(String tenantId, String versionId) {
|
ElnFieldVersionEntity item = versions.get(versionId);
|
return item != null && tenantId.equals(item.getFTenantId()) ? item : null;
|
}
|
}
|
|
private static ElnTemplateHealthService construct(ElnTemplateHealthServiceImpl.Store store,
|
ElnTemplateDocumentEvidence evidence,
|
ElnTemplateHealthServiceImpl.PendingReconciler reconciler,
|
java.util.function.Supplier<String> tenantSupplier,
|
List<ElnTemplateBindingDependencyValidator> validators,
|
ElnTemplateHealthServiceImpl.RepeatGroupReader repeatGroupReader,
|
ElnTemplateHealthServiceImpl.CheckboxGroupReader checkboxGroupReader) {
|
try {
|
Constructor<ElnTemplateHealthServiceImpl> constructor =
|
ElnTemplateHealthServiceImpl.class.getDeclaredConstructor(
|
ElnTemplateHealthServiceImpl.Store.class,
|
ElnTemplateDocumentEvidence.class,
|
ElnTemplateHealthServiceImpl.PendingReconciler.class,
|
java.util.function.Supplier.class,
|
List.class,
|
ElnTemplateHealthServiceImpl.RepeatGroupReader.class,
|
ElnTemplateHealthServiceImpl.CheckboxGroupReader.class);
|
constructor.setAccessible(true);
|
return constructor.newInstance(store, evidence, reconciler, tenantSupplier,
|
validators, repeatGroupReader, checkboxGroupReader);
|
} catch (ReflectiveOperationException e) {
|
throw new AssertionError(e);
|
}
|
}
|
}
|