package jnpf.onlinedev.service;
|
|
import jnpf.base.UserInfo;
|
import jnpf.base.entity.VisualdevEntity;
|
import jnpf.base.mapper.UploadEditDraftMapper;
|
import jnpf.base.model.flow.DataModel;
|
import jnpf.base.model.uploadedit.UploadEditDraft;
|
import jnpf.base.service.*;
|
import jnpf.base.util.*;
|
import jnpf.exception.DataException;
|
import jnpf.exception.WorkFlowException;
|
import jnpf.flowable.model.filepermission.FilePermissionView;
|
import jnpf.onlinedev.util.FlowFormCustomUtils;
|
import jnpf.util.UserProvider;
|
import org.junit.jupiter.api.*;
|
import org.mockito.MockedStatic;
|
import java.util.*;
|
import java.util.function.Consumer;
|
import static org.mockito.Mockito.*;
|
import static org.mockito.ArgumentMatchers.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
|
public class WorkflowFileCheckpointServiceTest {
|
private VisualdevService models;
|
private FlowFormDataUtil data;
|
private FlowFormCustomUtils nativeForms;
|
private UploadEditDraftMapper drafts;
|
private UploadFilePermissionQuery permissions;
|
private WorkflowFileCheckpointService service;
|
private UploadEditDraft draft;
|
private MockedStatic<UserProvider> users;
|
private Map<String,Object> persisted;
|
@BeforeEach public void setup() {
|
jnpf.util.context.SpringContext.setApplicationContext(mock(org.springframework.context.ApplicationContext.class));
|
users = mockStatic(UserProvider.class); UserInfo user = new UserInfo(); user.setTenantId("0"); user.setUserId("reviewer");
|
users.when(UserProvider::getUser).thenReturn(user);
|
models = mock(VisualdevService.class); data = mock(FlowFormDataUtil.class); nativeForms = mock(FlowFormCustomUtils.class);
|
drafts = mock(UploadEditDraftMapper.class); permissions = mock(UploadFilePermissionQuery.class);
|
service = new WorkflowFileCheckpointService(models,data,nativeForms,drafts,permissions);
|
FilePermissionView view = FilePermissionView.legacy("task", "form"); view.setEnabled(true);
|
when(permissions.current("task", "form")).thenReturn(view);
|
when(models.getReleaseInfo("form")).thenReturn(new VisualdevEntity());
|
persisted = new HashMap<>(Map.of("id", "record", "flowTaskId", "task", "files", List.of(Map.of("fileId", "A")), "title", "persisted"));
|
when(data.getFilePermissionDataInfo(any(), eq("task"), any())).thenReturn(persisted);
|
draft = new UploadEditDraft(); draft.setTenantId("0"); draft.setModelId("form"); draft.setRecordId("record"); draft.setTaskId("task");
|
draft.setField("files"); draft.setBaselineJson("[{\"fileId\":\"A\"}]"); draft.setCurrentJson("[{\"fileId\":\"B\"}]");
|
draft.setId(UploadEditWorkingCopy.id("0", UploadEditDraftService.context(draft)));
|
when(drafts.lockRecord("0", "form", "record")).thenReturn(List.of(draft));
|
}
|
@AfterEach public void close() { users.close(); }
|
@Test public void checkpointsOnlyUsingPersistedDataAndContinuesAfterNativeSave() throws Exception {
|
when(nativeForms.checkpointWorkflowFiles(any(), any())).thenAnswer(call -> {
|
jnpf.base.model.flow.FlowFormDataModel model = call.getArgument(1);
|
assertEquals("persisted", model.getMap().get("title")); assertEquals("record",model.getId());
|
assertTrue(model.getSkipRequiredValidation());
|
model.getMap().put("files", List.of(Map.of("fileId", "B")));
|
DataModel saved = new DataModel(); saved.getWorkflowWorkingFields().add("files"); return saved;
|
});
|
List<Map<String,Object>> output = new ArrayList<>();
|
service.save("task", "form", Map.of("title", "unsaved opinion"), output::add);
|
assertEquals(1,output.size()); assertEquals("unsaved opinion",output.get(0).get("title"));
|
assertEquals(List.of(Map.of("fileId", "B")),output.get(0).get("files"));
|
}
|
@Test public void nativeFailurePreventsNodeContinuation() throws Exception {
|
when(nativeForms.checkpointWorkflowFiles(any(),any())).thenThrow(new WorkFlowException("native failed"));
|
Consumer<Map<String,Object>> continuation = mock(Consumer.class);
|
try { service.save("task","form",Map.of(),continuation); fail("must reject"); } catch (DataException expected) { }
|
verifyNoInteractions(continuation);
|
}
|
@Test public void openLeasePreventsNativeSaveAndContinuation() {
|
draft.setLeaseId("active"); draft.setUpdatedAt(new Date());
|
Consumer<Map<String,Object>> continuation = mock(Consumer.class);
|
try { service.save("task","form",Map.of(),continuation); fail("must reject"); } catch (DataException expected) { }
|
verifyNoInteractions(nativeForms, continuation);
|
}
|
@Test public void unchangedWorkingFileDoesNotWriteNativeForm() {
|
draft.setCurrentJson(draft.getBaselineJson()); List<Map<String,Object>> output = new ArrayList<>();
|
service.save("task","form",Map.of("opinion","keep"),output::add);
|
assertEquals("keep",output.get(0).get("opinion")); verifyNoInteractions(nativeForms);
|
}
|
@Test public void mismatchedInstanceCannotCheckpoint() {
|
persisted.put("flowTaskId", "other"); Consumer<Map<String,Object>> continuation = mock(Consumer.class);
|
try { service.save("task","form",Map.of(),continuation); fail("instance"); } catch (DataException expected) { }
|
verifyNoInteractions(nativeForms, continuation, drafts);
|
}
|
@Test public void checkpointPassesHandlingReferenceToNativeSave() throws Exception {
|
when(nativeForms.checkpointWorkflowFiles(any(), any())).thenAnswer(call -> {
|
jnpf.base.model.flow.FlowFormDataModel model = call.getArgument(1);
|
assertEquals("operator-round-2", model.getWorkflowOperatorId());
|
return new DataModel();
|
});
|
service.save("task", "form", "operator-round-2", Map.of(), saved -> { });
|
verify(nativeForms, times(1)).checkpointWorkflowFiles(any(), any());
|
}
|
}
|