package jnpf.bizcommon.onlyoffice.service.impl;
|
|
import com.sun.net.httpserver.HttpServer;
|
import jnpf.base.UserInfo;
|
import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeConfigParam;
|
import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeCallbackParam;
|
import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeProperties;
|
import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeSessionEntity;
|
import jnpf.bizcommon.onlyoffice.mapper.OnlyOfficeSessionMapper;
|
import jnpf.exception.DataException;
|
import jnpf.file.FileApi;
|
import jnpf.file.FileUploadApi;
|
import org.junit.After;
|
import org.junit.Before;
|
import org.junit.Test;
|
|
import java.net.InetSocketAddress;
|
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Method;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Map;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.fail;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.eq;
|
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 OnlyOfficeServiceImplTest {
|
|
private HttpServer server;
|
private OnlyOfficeSessionMapper sessionMapper;
|
private FileApi fileApi;
|
private FileUploadApi fileUploadApi;
|
private OnlyOfficeServiceImpl service;
|
|
@Before
|
public void setUp() throws Exception {
|
server = HttpServer.create(new InetSocketAddress(0), 0);
|
server.createContext("/saved.docx", exchange -> {
|
byte[] body = "saved-document".getBytes();
|
exchange.sendResponseHeaders(200, body.length);
|
exchange.getResponseBody().write(body);
|
exchange.close();
|
});
|
server.start();
|
|
sessionMapper = mock(OnlyOfficeSessionMapper.class);
|
fileApi = mock(FileApi.class);
|
fileUploadApi = mock(FileUploadApi.class);
|
when(fileApi.getPath("annex")).thenReturn("WebAnnexFile");
|
OnlyOfficeProperties properties = new OnlyOfficeProperties();
|
properties.setJwtSecret("test-secret");
|
service = new OnlyOfficeServiceImpl(properties, sessionMapper,
|
mock(OnlyOfficePluginResolver.class), mock(OnlyOfficeFillTicketIssuer.class), fileApi, fileUploadApi);
|
}
|
|
@After
|
public void tearDown() {
|
server.stop(0);
|
}
|
|
@Test
|
public void saveBackReplacesOriginalFile() {
|
OnlyOfficeSessionEntity session = session();
|
when(fileUploadApi.replaceFile(any(), eq("WebAnnexFile/"), eq("template.docx"))).thenReturn(true);
|
|
invokeSaveBack(session, callback(), true);
|
|
verify(fileUploadApi).replaceFile(any(), eq("WebAnnexFile/"), eq("template.docx"));
|
verify(fileUploadApi, never()).uploadFile(any(), any(), any());
|
assertEquals(Integer.valueOf(2), session.getVersionNo());
|
}
|
|
@Test
|
public void failedReplacementDoesNotAdvanceSession() {
|
OnlyOfficeSessionEntity session = session();
|
when(fileUploadApi.replaceFile(any(), eq("WebAnnexFile/"), eq("template.docx"))).thenReturn(false);
|
|
try {
|
invokeSaveBack(session, callback(), true);
|
fail("expected replacement failure");
|
} catch (DataException e) {
|
assertEquals("文件服务写回文档失败", e.getMessage());
|
}
|
|
assertEquals(Integer.valueOf(1), session.getVersionNo());
|
assertNull(session.getLastSaveTime());
|
verify(sessionMapper, never()).updateById(any(OnlyOfficeSessionEntity.class));
|
}
|
|
@Test
|
public void viewModeHidesCollaborationMenu() {
|
OnlyOfficeConfigParam param = new OnlyOfficeConfigParam();
|
param.setFileId("template.docx");
|
param.setFileName("template.docx");
|
param.setBizScene("ordinary.view");
|
UserInfo user = new UserInfo();
|
user.setUserId("user-1");
|
user.setUserName("Tester");
|
|
Map<String, Object> config = invokeAssembleConfig(param, session(), user);
|
Map<String, Object> document = castMap(config.get("document"));
|
Map<String, Object> permissions = castMap(document.get("permissions"));
|
Map<String, Object> editorConfig = castMap(config.get("editorConfig"));
|
Map<String, Object> customization = castMap(editorConfig.get("customization"));
|
|
assertEquals(false, permissions.get("comment"));
|
assertEquals(false, permissions.get("review"));
|
assertEquals(false, customization.get("comments"));
|
}
|
|
private OnlyOfficeSessionEntity session() {
|
OnlyOfficeSessionEntity session = new OnlyOfficeSessionEntity();
|
session.setFileId("template.docx");
|
session.setFileType("annex");
|
session.setVersionNo(1);
|
session.setDocKey("key-1");
|
return session;
|
}
|
|
private OnlyOfficeCallbackParam callback() {
|
OnlyOfficeCallbackParam callback = new OnlyOfficeCallbackParam();
|
callback.setStatus(OnlyOfficeCallbackParam.Status.READY_FOR_SAVING);
|
callback.setUrl("http://127.0.0.1:" + server.getAddress().getPort() + "/saved.docx");
|
return callback;
|
}
|
|
private void invokeSaveBack(OnlyOfficeSessionEntity session, OnlyOfficeCallbackParam callback, boolean rotateKey) {
|
try {
|
Method method = OnlyOfficeServiceImpl.class.getDeclaredMethod(
|
"saveBack", OnlyOfficeSessionEntity.class, OnlyOfficeCallbackParam.class, boolean.class);
|
method.setAccessible(true);
|
method.invoke(service, session, callback, rotateKey);
|
} catch (InvocationTargetException e) {
|
if (e.getCause() instanceof RuntimeException) {
|
throw (RuntimeException) e.getCause();
|
}
|
throw new RuntimeException(e.getCause());
|
} catch (ReflectiveOperationException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
|
@SuppressWarnings("unchecked")
|
private Map<String, Object> invokeAssembleConfig(OnlyOfficeConfigParam param,
|
OnlyOfficeSessionEntity session,
|
UserInfo user) {
|
try {
|
Method method = OnlyOfficeServiceImpl.class.getDeclaredMethod("assembleConfig",
|
OnlyOfficeConfigParam.class, OnlyOfficeSessionEntity.class, String.class, String.class,
|
String.class, UserInfo.class, List.class);
|
method.setAccessible(true);
|
return (Map<String, Object>) method.invoke(service, param, session, "word", "docx", "view", user,
|
Collections.emptyList());
|
} catch (ReflectiveOperationException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
|
@SuppressWarnings("unchecked")
|
private Map<String, Object> castMap(Object value) {
|
return (Map<String, Object>) value;
|
}
|
}
|