/* @vitest-environment happy-dom */
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { defHttp } from '#/api/request';
|
import { createDmsFileDownloadTicket, downloadDmsFile } from '#/api/x/dms/personalFolder';
|
import { onlineUtils } from '#/utils/jnpf';
|
|
import { normalizeOfficeDocumentConfig, resolveFileName, resolveOnlyOfficeEditorMode, validateOfficeDocumentConfig } from '../helpers/officeDocument';
|
|
const mocks = vi.hoisted(() => ({ imagePreview: vi.fn(), openDmsReprint: vi.fn() }));
|
|
vi.mock('#/router', () => ({ router: { push: vi.fn() } }));
|
vi.mock('#/api/request', () => ({ defHttp: { get: vi.fn(), post: vi.fn() } }));
|
vi.mock('@jnpf/ui', () => ({ createImgPreview: mocks.imagePreview }));
|
vi.mock('#/views/x/dms/shared/dmsHiprint', () => ({
|
normalizeDmsPrintOptions: (options: any) => ({ copies: options?.copies ?? 1, pages: options?.pages, pageVariables: options?.pageVariables ?? [] }),
|
}));
|
|
vi.mock('#/views/x/dms/shared/dmsReprint', () => ({ openDmsReprint: mocks.openDmsReprint }));
|
|
const FILE = { fileId: 'file_001', name: '检验报告.docx' };
|
|
describe('onlineUtils.openOfficeDocument', () => {
|
it('emits OPEN_OFFICE_DOCUMENT with config', () => {
|
const emitter = onlineUtils.getEmitter();
|
const listener = vi.fn();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
const config = { file: FILE, mode: 'view' as const };
|
onlineUtils.openOfficeDocument(config);
|
|
expect(listener).toHaveBeenCalledWith(config);
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it('does not emit when fileId is missing', () => {
|
const emitter = onlineUtils.getEmitter();
|
const listener = vi.fn();
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
onlineUtils.openOfficeDocument({ file: { name: '无 id.docx' } as any });
|
|
expect(listener).not.toHaveBeenCalled();
|
expect(errorSpy).toHaveBeenCalledWith('[onlineUtils.openOfficeDocument] file.fileId is required');
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
errorSpy.mockRestore();
|
});
|
it('notifies the caller when no document window is listening', () => {
|
const onOpenError = vi.fn();
|
onlineUtils.openOfficeDocument({ file: FILE, onOpenError });
|
expect(onOpenError).toHaveBeenCalledWith(expect.objectContaining({ message: '文档窗口尚未就绪,请刷新页面后重试' }));
|
});
|
});
|
|
describe('onlineUtils.previewDmsFile', () => {
|
beforeEach(() => {
|
vi.mocked(defHttp.get).mockReset();
|
vi.mocked(defHttp.post).mockReset();
|
mocks.imagePreview.mockReset();
|
});
|
|
it('重打发送能力只透传给预览,不在入口执行', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({ data: { accessTicket: 'ticket', fileVersionId: 'version', fileName: '文件.docx' } });
|
const send = vi.fn(); const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter(); emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
try {
|
await onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version', showPrintButton: true,
|
reprint: { requestId: 'request', printRecordId: 'record', send }, printOptions: { copies: 1 },
|
});
|
expect(listener.mock.calls[0]![0].dmsPrint.reprint.send).toBe(send);
|
expect(send).not.toHaveBeenCalled();
|
} finally { emitter.off('OPEN_OFFICE_DOCUMENT', listener); }
|
});
|
it('blocks repeated print-preview entry without a global mask and releases the guard on failure', async () => {
|
let rejectTicket!: (error: Error) => void;
|
vi.mocked(defHttp.post).mockImplementationOnce(() => new Promise((_resolve, reject) => { rejectTicket = reject; }));
|
const options = { wenjianZhongxinId: 'version', showPrintButton: true };
|
const opening = onlineUtils.previewDmsFile(options);
|
const failed = expect(opening).rejects.toThrow('ticket failed');
|
await vi.waitFor(() => expect(defHttp.post).toHaveBeenCalledTimes(1));
|
expect(document.querySelector('[data-jnpf-loading]')).toBeNull();
|
await expect(onlineUtils.previewDmsFile(options)).resolves.toBe(false);
|
expect(defHttp.post).toHaveBeenCalledTimes(1);
|
rejectTicket(new Error('ticket failed'));
|
await failed;
|
expect(document.querySelector('[data-jnpf-loading]')).toBeNull();
|
vi.mocked(defHttp.post).mockRejectedValueOnce(new Error('retry reached'));
|
await expect(onlineUtils.previewDmsFile(options)).rejects.toThrow('retry reached');
|
expect(document.querySelector('[data-jnpf-loading]')).toBeNull();
|
});
|
|
it('preserves a global loading mask owned by the caller when preview entry fails', async () => {
|
onlineUtils.showLoading('caller');
|
const callerMask = document.querySelector('[data-jnpf-loading]');
|
try {
|
vi.mocked(defHttp.post).mockRejectedValueOnce(new Error('ticket failed'));
|
await expect(onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version', showPrintButton: true })).rejects.toThrow('ticket failed');
|
expect(document.querySelector('[data-jnpf-loading]')).toBe(callerMask);
|
} finally {
|
onlineUtils.hideLoading();
|
}
|
});
|
|
it('opens the preview directly when a file-center version ID is provided', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: {
|
accessTicket: 'direct-preview-ticket',
|
fileName: '直接预览.docx',
|
fileVersionId: 'direct-file-center-version',
|
sizeBytes: 2048,
|
},
|
} as any);
|
const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
await expect(onlineUtils.previewDmsFile({ wenjianZhongxinId: ' direct-file-center-version ' })).resolves.toBe(true);
|
|
expect(defHttp.get).not.toHaveBeenCalled();
|
expect(defHttp.post).toHaveBeenCalledWith(
|
{
|
data: expect.objectContaining({
|
previewFormat: 'pdf',
|
resourceId: 'direct-file-center-version',
|
resourceType: 'FILE_VERSION',
|
watermarkType: '',
|
}),
|
url: '/api/dms/file-preview-tickets',
|
},
|
{ errorMessageMode: 'none' },
|
);
|
expect(listener).toHaveBeenCalledWith({
|
dmsAccessTicket: 'direct-preview-ticket',
|
dmsPreviewExpiresAt: undefined,
|
refreshDmsPreviewTicket: expect.any(Function),
|
file: { fileId: 'direct-file-center-version', fileSize: 2048, name: '直接预览.docx' },
|
fileType: 'dms',
|
mode: 'view',
|
title: '直接预览.docx',
|
});
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it.each(['download', 'print', 'preview', 'other'])('passes watermarkType %s to initial and refreshed preview tickets', async (watermarkType) => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: { accessTicket: 'preview-ticket', fileName: 'quality.docx', fileVersionId: 'version-1' },
|
} as any);
|
const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
await onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version-1', watermarkType });
|
const config = listener.mock.calls[0]![0];
|
await config.refreshDmsPreviewTicket();
|
|
expect(vi.mocked(defHttp.post).mock.calls.map(([request]) => request.data.watermarkType)).toEqual([watermarkType, watermarkType]);
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it('allows callers to retain the source preview format', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: {
|
accessTicket: 'source-preview-ticket',
|
fileName: '直接预览.docx',
|
fileVersionId: 'direct-file-center-version',
|
},
|
} as any);
|
|
await onlineUtils.previewDmsFile({
|
previewFormat: 'source',
|
wenjianZhongxinId: 'direct-file-center-version',
|
});
|
|
expect(defHttp.post).toHaveBeenCalledWith(
|
{
|
data: expect.objectContaining({ previewFormat: 'source' }),
|
url: '/api/dms/file-preview-tickets',
|
},
|
{ errorMessageMode: 'none' },
|
);
|
});
|
|
it('opens image tickets with the JNPF image preview instead of OnlyOffice', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: {
|
accessTicket: 'image-preview-ticket',
|
fileName: 'evidence.png',
|
fileVersionId: 'image-version',
|
mimeType: 'image/png',
|
},
|
} as any);
|
const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
await expect(onlineUtils.previewDmsFile({ wenjianZhongxinId: 'image-version' })).resolves.toBe(true);
|
|
expect(mocks.imagePreview).toHaveBeenCalledWith({
|
imageList: [expect.stringContaining('/api/file/Dms/OnlyOffice/image-version?ticket=image-preview-ticket')],
|
});
|
expect(listener).not.toHaveBeenCalled();
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it('rejects conflicting file locators before creating a ticket', async () => {
|
await expect(
|
onlineUtils.previewDmsFile({
|
versionId: 'business-version',
|
wenjianZhongxinId: 'file-center-version',
|
}),
|
).rejects.toThrow('DMS 文件定位参数只能使用');
|
|
expect(defHttp.get).not.toHaveBeenCalled();
|
expect(defHttp.post).not.toHaveBeenCalled();
|
});
|
|
it('creates a preview ticket with an explicit DMS resource locator', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: {
|
accessTicket: 'document-preview-ticket',
|
fileName: '受控文件.docx',
|
fileVersionId: 'fixed-file-version',
|
},
|
} as any);
|
|
await expect(onlineUtils.previewDmsFile({ resourceId: 'document-1', resourceType: 'DOCUMENT' })).resolves.toBe(true);
|
|
expect(defHttp.post).toHaveBeenCalledWith(
|
{
|
data: expect.objectContaining({ resourceId: 'document-1', resourceType: 'DOCUMENT' }),
|
url: '/api/dms/file-preview-tickets',
|
},
|
{ errorMessageMode: 'none' },
|
);
|
});
|
|
it('keeps page variables in the normalized front-end print context', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: {
|
accessTicket: 'preview-ticket',
|
fileName: '受控文件.docx',
|
fileVersionId: 'fixed-file-version',
|
},
|
} as any);
|
const listener = vi.fn();
|
const beforePrint = vi.fn();
|
const confirmPrint = vi.fn();
|
const onPrintSuccess = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
await onlineUtils.previewDmsFile({
|
beforePrint,
|
confirmPrint,
|
printQuantity: { total: 10, printed: 2 },
|
closeOnPrintSuccess: true,
|
onPrintSuccess,
|
resourceId: 'file-version-1',
|
resourceType: 'FILE_VERSION',
|
showPrintButton: true,
|
printOptions: { copies: 2, pages: '1-2', pageVariables: [{ pageNo: 1, variables: { code: 'A-001' } }] },
|
});
|
|
expect(defHttp.post).toHaveBeenCalledWith(
|
expect.objectContaining({ data: expect.not.objectContaining({ pageVariables: expect.anything() }) }),
|
expect.anything(),
|
);
|
expect(listener).toHaveBeenCalledWith(
|
expect.objectContaining({
|
dmsPrint: {
|
beforePrint,
|
confirmPrint,
|
printQuantity: { total: 10, printed: 2 },
|
closeOnPrintSuccess: true,
|
copies: 2,
|
fileVersionId: 'fixed-file-version',
|
onPrintSuccess,
|
pages: '1-2',
|
pageVariables: [{ pageNo: 1, variables: { code: 'A-001' } }],
|
},
|
}),
|
);
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it('queries the file-center version and opens a read-only DMS preview', async () => {
|
vi.mocked(defHttp.get).mockResolvedValue({ data: { wenjianZhongxinBanbenId: 'file-center-version-1' } } as any);
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: {
|
accessTicket: 'preview-ticket',
|
fileName: '质量文件.docx',
|
fileVersionId: 'file-center-version-1',
|
sizeBytes: 1024,
|
},
|
} as any);
|
const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
|
await expect(onlineUtils.previewDmsFile({ versionId: ' business-version-1 ' })).resolves.toBe(true);
|
|
expect(defHttp.get).toHaveBeenCalledWith(
|
{ url: '/api/dms/biz/wenjian/banben/file-versions/business-version-1/file-center-version' },
|
{ errorMessageMode: 'none' },
|
);
|
expect(defHttp.post).toHaveBeenCalledWith(
|
{
|
data: expect.objectContaining({ resourceId: 'file-center-version-1', resourceType: 'FILE_VERSION' }),
|
url: '/api/dms/file-preview-tickets',
|
},
|
{ errorMessageMode: 'none' },
|
);
|
expect(listener).toHaveBeenCalledWith({
|
dmsAccessTicket: 'preview-ticket',
|
dmsPreviewExpiresAt: undefined,
|
refreshDmsPreviewTicket: expect.any(Function),
|
file: { fileId: 'file-center-version-1', fileSize: 1024, name: '质量文件.docx' },
|
fileType: 'dms',
|
mode: 'view',
|
title: '质量文件.docx',
|
});
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it('filters a forged control status while preserving barcode entries for preview, print and download tickets', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({
|
data: { accessTicket: 'scene-ticket', fileName: 'quality.docx', fileVersionId: 'version-1' },
|
} as any);
|
const options = {
|
wenjianZhongxinId: 'version-1',
|
customBarcode: [
|
{ page: 4, barValue: 'REC-004', barText: '中文 <&> {/CUN}' },
|
{ page: 4, barValue: 'SECOND-004', barText: 'Another label' },
|
{ barValue: 'EVERY-PAGE', barText: 'All pages' },
|
],
|
shifouShoukong: 'no',
|
} as any;
|
await onlineUtils.previewDmsFile(options);
|
await onlineUtils.printDmsFile({ ...options, copies: 2, printPages: '2-3' });
|
await createDmsFileDownloadTicket('version-1', options);
|
expect(defHttp.post).toHaveBeenNthCalledWith(
|
1,
|
{
|
url: '/api/dms/file-preview-tickets',
|
data: expect.objectContaining({ customBarcode: options.customBarcode }),
|
},
|
{ errorMessageMode: 'none' },
|
);
|
expect(defHttp.post).toHaveBeenNthCalledWith(
|
3,
|
{
|
url: '/api/dms/file-download-tickets',
|
data: expect.objectContaining({ customBarcode: options.customBarcode }),
|
},
|
{ errorMessageMode: 'none' },
|
);
|
expect(defHttp.post).toHaveBeenNthCalledWith(
|
2,
|
{
|
url: '/api/dms/file-print-tickets',
|
data: expect.objectContaining({ customBarcode: options.customBarcode, copies: 2, printPages: '2-3' }),
|
},
|
{ errorMessageMode: 'none' },
|
);
|
vi.mocked(defHttp.post)
|
.mock.calls.slice(0, 3)
|
.forEach(([request]) => {
|
expect(request).toBeDefined();
|
expect(request!.data).not.toHaveProperty('shifouShoukong');
|
});
|
});
|
|
it('loads fixed task barcode parameters and retains the print scene on ticket renewal', async () => {
|
const buildCustomBarcode = async ({ serialNumber, countSerialNumber }: any) => [{ barValue: serialNumber, barText: `流水 ${serialNumber} / ${countSerialNumber}` }];
|
const customBarcode = await buildCustomBarcode({ serialNumber: 'SERIAL-3', countSerialNumber: '20260003' });
|
vi.mocked(defHttp.post).mockImplementation(async (request: any) => {
|
if (request.url.endsWith('/yulan-canshu')) return { code: 200, data: { serialNumber: 'SERIAL-3', countSerialNumber: '20260003' } } as any;
|
return { data: { accessTicket: 'preview-ticket', fileName: 'quality.docx', fileVersionId: 'version-1' } } as any;
|
});
|
const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
try {
|
await onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version-1', showPrintButton: true, printTaskId: 'task-1', buildCustomBarcode });
|
expect(listener.mock.calls[0]![0].dmsPrint.buildCustomBarcode).toBe(buildCustomBarcode);
|
await listener.mock.calls[0]![0].refreshDmsPreviewTicket();
|
expect(defHttp.post).toHaveBeenNthCalledWith(1, {
|
url: '/api/dms/biz/wenjian/dayin/renwu/yulan-canshu', data: { taskId: 'task-1', fileVersionId: 'version-1' },
|
}, expect.anything());
|
expect(defHttp.post).toHaveBeenCalledTimes(3);
|
for (const [request] of vi.mocked(defHttp.post).mock.calls.slice(1)) {
|
expect(request).toMatchObject({ url: '/api/dms/file-preview-tickets', data: { watermarkType: 'print', customBarcode } });
|
}
|
} finally {
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
}
|
});
|
|
it('does not open an unmarked preview or send attempt if loading task parameters fails', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({ code: 400, msg: '无当前打印任务的操作权限' } as any);
|
await expect(onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version-1', showPrintButton: true, printTaskId: 'task-1' }))
|
.rejects.toThrow('无当前打印任务的操作权限');
|
expect(defHttp.post).toHaveBeenCalledTimes(1);
|
});
|
|
it('rejects empty barcode parameters instead of silently opening an unmarked preview', async () => {
|
vi.mocked(defHttp.post).mockResolvedValue({ code: 200, data: { customBarcode: [] } } as any);
|
await expect(onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version-1', showPrintButton: true, printTaskId: 'task-1' }))
|
.rejects.toThrow('任务固定流水号缺失');
|
expect(defHttp.post).toHaveBeenCalledTimes(1);
|
});
|
|
it('retains a copy of barcode entries for the preview toolbar print action', async () => {
|
const customBarcode = [{ page: 4, barValue: 'REC-004', barText: 'Page four' }];
|
vi.mocked(defHttp.post).mockImplementation(async () => {
|
customBarcode[0]!.barText = 'Changed while awaiting the preview ticket';
|
return { data: { accessTicket: 'preview-ticket', fileName: 'quality.docx', fileVersionId: 'version-1' } } as any;
|
});
|
const listener = vi.fn();
|
const emitter = onlineUtils.getEmitter();
|
emitter.on('OPEN_OFFICE_DOCUMENT', listener);
|
await onlineUtils.previewDmsFile({ wenjianZhongxinId: 'version-1', showPrintButton: true, customBarcode });
|
customBarcode[0]!.barText = 'Changed by caller';
|
expect(listener).toHaveBeenCalledWith(
|
expect.objectContaining({
|
dmsPrint: expect.objectContaining({
|
fileVersionId: 'version-1',
|
customBarcode: [{ page: 4, barValue: 'REC-004', barText: 'Page four' }],
|
}),
|
}),
|
);
|
emitter.off('OPEN_OFFICE_DOCUMENT', listener);
|
});
|
|
it('does not create a preview ticket when the business version has no file-center version', async () => {
|
vi.mocked(defHttp.get).mockResolvedValue({ data: {} } as any);
|
|
await expect(onlineUtils.previewDmsFile({ versionId: 'business-version-1' })).resolves.toBe(false);
|
|
expect(defHttp.post).not.toHaveBeenCalled();
|
});
|
|
it('shows a development notice when no supported preview parameter is provided', async () => {
|
const toastSpy = vi.spyOn(onlineUtils, 'toast').mockImplementation(() => {});
|
|
await expect(onlineUtils.previewDmsFile({ fileId: 'file-1' } as any)).resolves.toBe(false);
|
await expect(onlineUtils.previewDmsFile({ versionId: ' ' })).resolves.toBe(false);
|
|
expect(toastSpy).toHaveBeenCalledTimes(2);
|
expect(toastSpy).toHaveBeenCalledWith('业务开发中', 'info');
|
expect(defHttp.get).not.toHaveBeenCalled();
|
expect(defHttp.post).not.toHaveBeenCalled();
|
toastSpy.mockRestore();
|
});
|
});
|
|
describe('DMS download format', () => {
|
it('keeps original downloads compatible and allows requesting a PDF blob', async () => {
|
vi.mocked(defHttp.get).mockReset();
|
const blob = new Blob(['pdf'], { type: 'application/pdf' });
|
vi.mocked(defHttp.get).mockResolvedValue(blob);
|
await downloadDmsFile('version-1', 'download-ticket');
|
expect(defHttp.get).toHaveBeenLastCalledWith(
|
{ url: '/api/file/Dms/Download/version-1', params: { ticket: 'download-ticket' }, responseType: 'blob' },
|
{ errorMessageMode: 'none', isTransformResponse: false },
|
);
|
await expect(downloadDmsFile('version-1', 'download-ticket', 'pdf')).resolves.toBe(blob);
|
expect(defHttp.get).toHaveBeenLastCalledWith(
|
{
|
url: '/api/file/Dms/Download/version-1',
|
params: { ticket: 'download-ticket', format: 'pdf' },
|
responseType: 'blob',
|
timeout: 300_000,
|
},
|
{ errorMessageMode: 'none', isTransformResponse: false },
|
);
|
});
|
});
|
|
describe('officeDocument helpers', () => {
|
it('文件名缺失时从 url 兜底截取(后端靠扩展名定 documentType,丢了就打不开)', () => {
|
expect(resolveFileName({ file: { fileId: 'f1', name: '' } } as any)).toBe('');
|
expect(resolveFileName({ file: { fileId: 'f1', name: '', url: '/api/file/annex/a.docx?s=k' } } as any)).toBe('a.docx');
|
expect(resolveFileName({ file: { fileId: 'f1', name: '', url: '/api/file/annex/noext' } } as any)).toBe('');
|
});
|
|
it('校验必填项', () => {
|
expect(() => validateOfficeDocumentConfig({ file: { name: 'a.docx' } } as any)).toThrow('file.fileId is required');
|
expect(() => validateOfficeDocumentConfig({ file: { fileId: 'f1', name: '' } } as any)).toThrow('file.name is required');
|
expect(() => validateOfficeDocumentConfig({ file: FILE })).not.toThrow();
|
});
|
|
it('归一化:mode 默认 edit,标题默认取文件名', () => {
|
expect(normalizeOfficeDocumentConfig({ file: FILE })).toMatchObject({ mode: 'edit', title: '检验报告.docx' });
|
expect(normalizeOfficeDocumentConfig({ file: FILE, mode: 'view', title: ' 自定义 ' })).toMatchObject({
|
mode: 'view',
|
title: '自定义',
|
});
|
expect(normalizeOfficeDocumentConfig({ file: FILE, mode: 'qianpiye' })).toMatchObject({
|
bizModule: 'dms',
|
bizScene: 'dms.qianpiye',
|
mode: 'qianpiye',
|
});
|
expect(
|
normalizeOfficeDocumentConfig({
|
bizModule: '签批页管理模块标识',
|
bizScene: 'custom.scene',
|
file: FILE,
|
mode: 'qianpiye',
|
}),
|
).toMatchObject({ bizModule: 'dms', bizScene: 'dms.qianpiye' });
|
expect(resolveOnlyOfficeEditorMode('qianpiye')).toBe('edit');
|
expect(() => normalizeOfficeDocumentConfig({ file: FILE, mode: 'readonly' as any })).toThrow('不支持');
|
expect(normalizeOfficeDocumentConfig({ file: FILE, mode: 'review' }).mode).toBe('review');
|
expect(resolveOnlyOfficeEditorMode('review')).toBe('edit');
|
expect(normalizeOfficeDocumentConfig({ file: FILE, mode: 'viewComments' }).mode).toBe('viewComments');
|
expect(resolveOnlyOfficeEditorMode('viewComments')).toBe('view');
|
});
|
});
|
|
describe('onlineUtils.openDmsReprint loading', () => {
|
it.each([false, true])('does not create global loading and releases the guard after failure=%s', async (fails) => {
|
let finish!: () => void;
|
mocks.openDmsReprint.mockReset();
|
mocks.openDmsReprint.mockImplementationOnce(
|
() =>
|
new Promise<void>((resolve, reject) => {
|
finish = () => (fails ? reject(new Error('reprint failed')) : resolve());
|
}),
|
);
|
const opening = onlineUtils.openDmsReprint('record');
|
const result = fails ? expect(opening).rejects.toThrow('reprint failed') : expect(opening).resolves.toBeUndefined();
|
await vi.waitFor(() => expect(mocks.openDmsReprint).toHaveBeenCalledTimes(1));
|
expect(document.querySelector('[data-jnpf-loading]')).toBeNull();
|
await onlineUtils.openDmsReprint('record');
|
expect(mocks.openDmsReprint).toHaveBeenCalledTimes(1);
|
finish();
|
await result;
|
expect(document.querySelector('[data-jnpf-loading]')).toBeNull();
|
mocks.openDmsReprint.mockResolvedValueOnce(undefined);
|
await onlineUtils.openDmsReprint('record');
|
expect(mocks.openDmsReprint).toHaveBeenCalledTimes(2);
|
expect(document.querySelector('[data-jnpf-loading]')).toBeNull();
|
});
|
|
it('preserves loading owned by the caller', async () => {
|
onlineUtils.showLoading('caller');
|
const mask = document.querySelector('[data-jnpf-loading]');
|
try {
|
mocks.openDmsReprint.mockRejectedValueOnce(new Error('reprint failed'));
|
await expect(onlineUtils.openDmsReprint('record')).rejects.toThrow('reprint failed');
|
expect(document.querySelector('[data-jnpf-loading]')).toBe(mask);
|
} finally {
|
onlineUtils.hideLoading();
|
}
|
});
|
});
|