From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master
---
jnpf-biz-common/jnpf-biz-common-onlyoffice/src/test/java/jnpf/bizcommon/onlyoffice/service/impl/OnlyOfficeServiceImplTest.java | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 170 insertions(+), 0 deletions(-)
diff --git a/jnpf-biz-common/jnpf-biz-common-onlyoffice/src/test/java/jnpf/bizcommon/onlyoffice/service/impl/OnlyOfficeServiceImplTest.java b/jnpf-biz-common/jnpf-biz-common-onlyoffice/src/test/java/jnpf/bizcommon/onlyoffice/service/impl/OnlyOfficeServiceImplTest.java
new file mode 100644
index 0000000..13893d5
--- /dev/null
+++ b/jnpf-biz-common/jnpf-biz-common-onlyoffice/src/test/java/jnpf/bizcommon/onlyoffice/service/impl/OnlyOfficeServiceImplTest.java
@@ -0,0 +1,170 @@
+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;
+ }
+}
--
Gitblit v1.8.0