import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { useLaunchDelete } from './useLaunchDelete';
|
|
const mocks = vi.hoisted(() => ({
|
confirm: vi.fn(),
|
error: vi.fn(),
|
getInfo: vi.fn(),
|
hideLoading: vi.fn(),
|
reload: vi.fn(),
|
remove: vi.fn(),
|
sign: vi.fn(),
|
showLoading: vi.fn(),
|
success: vi.fn(),
|
}));
|
|
vi.mock('@jnpf/hooks', () => ({ useMessage: () => ({ createConfirm: mocks.confirm, createMessage: mocks }) }));
|
vi.mock('#/api/workFlow/task', () => ({ delFlowLaunch: mocks.remove, getFlowTaskInfo: mocks.getInfo }));
|
vi.mock('#/locales', () => ({ $t: (key: string) => key }));
|
vi.mock('#/utils/jnpf', () => ({ onlineUtils: { hideLoading: mocks.hideLoading, showLoading: mocks.showLoading, sign: mocks.sign } }));
|
|
const record = { id: 'task-1', flowId: 'flow-1' };
|
function detail(enabled = true) {
|
return {
|
data: {
|
formInfo: {
|
id: 'form-1',
|
columnData: JSON.stringify({ columnBtnsList: [{ value: 'remove', label: '废弃', event: { biz_sign_enabled: enabled } }] }),
|
},
|
formData: { id: 'business-1', title: '测试流程', biz_sign: 'historical-sign' },
|
},
|
};
|
}
|
|
describe('my initiated workflow deletion', () => {
|
beforeEach(() => {
|
vi.resetAllMocks();
|
mocks.getInfo.mockResolvedValue(detail());
|
mocks.remove.mockResolvedValue({ msg: '删除成功' });
|
});
|
|
it('reads the start form and signs before deleting with the fresh signature', async () => {
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
const pending = handleDelete(record);
|
expect(mocks.showLoading).toHaveBeenCalledOnce();
|
expect(mocks.hideLoading).not.toHaveBeenCalled();
|
expect(deleting.value).toBe(true);
|
await pending;
|
expect(mocks.getInfo).toHaveBeenCalledWith('task-1', { flowId: 'flow-1', opType: '-1' });
|
expect(mocks.confirm).not.toHaveBeenCalled();
|
expect(mocks.remove).not.toHaveBeenCalled();
|
const options = mocks.sign.mock.calls[0]![0];
|
expect(mocks.hideLoading).not.toHaveBeenCalled();
|
options.onOpen();
|
expect(mocks.hideLoading).toHaveBeenCalledOnce();
|
expect(deleting.value).toBe(true);
|
expect(options.metaData).toMatchObject({ biz_button: '废弃', biz_form_id: 'form-1', biz_data: [detail().data.formData], is_biz_form: false });
|
await options.onSubmit({ biz_sign: 'delete-sign' });
|
expect(mocks.remove).toHaveBeenCalledWith('task-1', { biz_sign: 'delete-sign' });
|
expect(mocks.reload).toHaveBeenCalledOnce();
|
expect(deleting.value).toBe(false);
|
expect(mocks.showLoading).toHaveBeenCalledTimes(2);
|
expect(mocks.hideLoading).toHaveBeenCalledTimes(2);
|
});
|
|
it('cancels signing without deleting and allows another attempt', async () => {
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
mocks.sign.mock.calls[0]![0].onCancel();
|
expect(mocks.hideLoading).toHaveBeenCalledOnce();
|
expect(mocks.remove).not.toHaveBeenCalled();
|
expect(deleting.value).toBe(false);
|
await handleDelete(record);
|
expect(mocks.sign).toHaveBeenCalledTimes(2);
|
});
|
|
it('does not delete when signing provides no valid credential', async () => {
|
const { handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
await mocks.sign.mock.calls[0]![0].onSubmit({});
|
expect(mocks.error).toHaveBeenCalled();
|
expect(mocks.remove).not.toHaveBeenCalled();
|
});
|
|
it('confirms an unsigned delete without reusing a historical signature', async () => {
|
mocks.getInfo.mockResolvedValue(detail(false));
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
expect(mocks.sign).not.toHaveBeenCalled();
|
expect(mocks.remove).not.toHaveBeenCalled();
|
expect(mocks.hideLoading).toHaveBeenCalledOnce();
|
await mocks.confirm.mock.calls[0]![0].onOk();
|
expect(mocks.remove).toHaveBeenCalledWith('task-1', undefined);
|
expect(deleting.value).toBe(false);
|
expect(mocks.hideLoading).toHaveBeenCalledTimes(2);
|
});
|
|
it('does not delete when the confirmation is cancelled', async () => {
|
mocks.getInfo.mockResolvedValue(detail(false));
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
mocks.confirm.mock.calls[0]![0].onCancel();
|
expect(mocks.remove).not.toHaveBeenCalled();
|
expect(deleting.value).toBe(false);
|
});
|
|
it('closes the full screen loading and releases the guard if the signature modal fails to open', async () => {
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
mocks.sign.mock.calls[0]![0].onOpenError(new Error('modal failed'));
|
expect(mocks.hideLoading).toHaveBeenCalledOnce();
|
expect(deleting.value).toBe(false);
|
expect(mocks.remove).not.toHaveBeenCalled();
|
});
|
|
it.each(['request', 'missing', 'malformed'])('stops deletion on %s configuration failure', async (failure) => {
|
if (failure === 'request') mocks.getInfo.mockRejectedValue(new Error('network'));
|
if (failure === 'missing') mocks.getInfo.mockResolvedValue({ data: {} });
|
if (failure === 'malformed') mocks.getInfo.mockResolvedValue({ data: { formInfo: { columnData: '{' } } });
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
expect(mocks.error).toHaveBeenCalled();
|
expect(mocks.sign).not.toHaveBeenCalled();
|
expect(mocks.confirm).not.toHaveBeenCalled();
|
expect(mocks.remove).not.toHaveBeenCalled();
|
expect(deleting.value).toBe(false);
|
expect(mocks.hideLoading).toHaveBeenCalledOnce();
|
});
|
|
it('prevents repeated clicks while the signature dialog is open', async () => {
|
const { handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
await handleDelete(record);
|
expect(mocks.getInfo).toHaveBeenCalledOnce();
|
expect(mocks.sign).toHaveBeenCalledOnce();
|
});
|
|
it('releases the busy state and does not reload if the delete fails', async () => {
|
mocks.remove.mockRejectedValue(new Error('delete failed'));
|
const { deleting, handleDelete } = useLaunchDelete(mocks.reload);
|
await handleDelete(record);
|
await expect(mocks.sign.mock.calls[0]![0].onSubmit({ biz_sign: 'delete-sign' })).rejects.toThrow('delete failed');
|
expect(deleting.value).toBe(false);
|
expect(mocks.reload).not.toHaveBeenCalled();
|
});
|
});
|