package jnpf.bizcommon.onlyoffice.service.impl;
|
|
import cn.hutool.http.HttpRequest;
|
import cn.hutool.http.HttpResponse;
|
import cn.hutool.http.HttpUtil;
|
import cn.hutool.jwt.JWTUtil;
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
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.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.junit.After;
|
import org.junit.Before;
|
import org.junit.Test;
|
import org.mockito.MockedStatic;
|
|
import java.nio.charset.StandardCharsets;
|
import java.util.Map;
|
|
import static org.junit.Assert.*;
|
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.Mockito.*;
|
|
/** 使用内存中的文档响应验证场景分发,不监听端口或访问外部文件服务。 */
|
public class UploadEditCallbackTest {
|
private OnlyOfficeSessionMapper sessionMapper;
|
private FileApi fileApi;
|
private FileUploadApi fileUploadApi;
|
private OnlyOfficeServiceImpl service;
|
private MockedStatic<HttpUtil> http;
|
|
@Before
|
public void setup() {
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), OnlyOfficeSessionEntity.class);
|
sessionMapper = mock(OnlyOfficeSessionMapper.class);
|
when(sessionMapper.update(isNull(), any())).thenReturn(1);
|
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, null, null, null, null, null,
|
fileApi, fileUploadApi, new DmsQianpiyeDocxPropertiesWriter());
|
http = mockStatic(HttpUtil.class);
|
HttpRequest request = mock(HttpRequest.class);
|
HttpResponse response = mock(HttpResponse.class);
|
http.when(() -> HttpUtil.createGet("http://document-server/saved.docx")).thenReturn(request);
|
when(request.timeout(anyInt())).thenReturn(request);
|
when(request.executeAsync()).thenReturn(response);
|
when(response.isOk()).thenReturn(true);
|
when(response.bodyBytes()).thenReturn("saved-document".getBytes(StandardCharsets.UTF_8));
|
}
|
|
@After
|
public void cleanup() {
|
if (http != null) http.close();
|
}
|
|
@Test
|
public void uploadCallbackSaveFailureUsesUploadSpecificException() {
|
OnlyOfficeSessionEntity session = session();
|
session.setBizModule("visualdev");
|
session.setBizScene("visualdev.uploadFile");
|
when(sessionMapper.selectOne(any())).thenReturn(session);
|
for (int status : new int[] {2, 6}) {
|
OnlyOfficeCallbackParam callback = callback();
|
callback.setKey(session.getDocKey());
|
callback.setStatus(status);
|
callback.setUrl(null);
|
Map<String, Object> claims = new java.util.LinkedHashMap<>();
|
claims.put("key", callback.getKey());
|
claims.put("status", status);
|
String token = JWTUtil.createToken(claims, "test-secret".getBytes(StandardCharsets.UTF_8));
|
try {
|
service.handleCallback(callback, "Bearer " + token);
|
fail("upload save without a source URL must fail");
|
} catch (jnpf.bizcommon.onlyoffice.exception.UploadEditCallbackException e) {
|
assertTrue(e.getCause() instanceof DataException);
|
assertTrue(e.getMessage().contains("缺少下载 url"));
|
}
|
}
|
verifyNoInteractions(fileApi);
|
verify(fileUploadApi, never()).replaceFile(any(), any(), any());
|
}
|
|
@Test
|
public void uploadCallbackSavesThroughUploadBranchOnly() throws Exception {
|
UploadEditSessionSupport support = mock(UploadEditSessionSupport.class);
|
java.lang.reflect.Field field = OnlyOfficeServiceImpl.class.getDeclaredField("uploadEditSessionSupport");
|
field.setAccessible(true);
|
field.set(service, support);
|
for (int status : new int[] {2, 6}) {
|
OnlyOfficeSessionEntity session = session();
|
session.setBizModule("visualdev");
|
session.setBizScene("visualdev.uploadFile");
|
session.setSessionStatus(OnlyOfficeSessionEntity.SessionStatus.EDITING);
|
when(sessionMapper.selectOne(any())).thenReturn(session);
|
OnlyOfficeCallbackParam callback = callback();
|
callback.setKey(session.getDocKey());
|
callback.setStatus(status);
|
Map<String, Object> claims = new java.util.LinkedHashMap<>();
|
claims.put("key", callback.getKey());
|
claims.put("status", status);
|
claims.put("url", callback.getUrl());
|
callback.setFiletype("docx");
|
claims.put("filetype", callback.getFiletype());
|
String token = JWTUtil.createToken(claims, "test-secret".getBytes(StandardCharsets.UTF_8));
|
|
service.handleCallback(callback, "Bearer " + token);
|
|
verify(support).save(eq(session), eq(callback), any(byte[].class));
|
}
|
http.verify(() -> HttpUtil.createGet("http://document-server/saved.docx"), times(2));
|
verify(fileUploadApi, never()).replaceFile(any(), any(), any());
|
}
|
|
@Test
|
public void nonUploadSaveFailureKeepsOriginalException() {
|
OnlyOfficeSessionEntity session = session();
|
session.setBizModule("other-business");
|
when(sessionMapper.selectOne(any())).thenReturn(session);
|
OnlyOfficeCallbackParam callback = callback();
|
callback.setUrl(null);
|
String token = JWTUtil.createToken(java.util.Collections.singletonMap("scope", "test"),
|
"test-secret".getBytes(StandardCharsets.UTF_8));
|
try {
|
service.handleCallback(callback, "Bearer " + token);
|
fail("invalid save must fail");
|
} catch (DataException e) {
|
assertTrue(e.getMessage().contains("缺少下载 url"));
|
}
|
http.verifyNoInteractions();
|
}
|
|
private OnlyOfficeSessionEntity session() {
|
OnlyOfficeSessionEntity session = new OnlyOfficeSessionEntity();
|
session.setId("session-1");
|
session.setTenantId("tenant-a");
|
session.setFileId("lease-1");
|
session.setFileType("annex");
|
session.setDocKey("key-1");
|
session.setVersionNo(1);
|
return session;
|
}
|
|
private OnlyOfficeCallbackParam callback() {
|
OnlyOfficeCallbackParam callback = new OnlyOfficeCallbackParam();
|
callback.setKey("key-1");
|
callback.setStatus(2);
|
callback.setUrl("http://document-server/saved.docx");
|
return callback;
|
}
|
}
|