刘光辉
4 小时以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* @vitest-environment happy-dom */
 
import { flushPromises, mount } from '@vue/test-utils';
 
import { beforeEach, describe, expect, it, vi } from 'vitest';
 
import SourcePathDrawer from '../SourcePathDrawer.vue';
import drawerSource from '../SourcePathDrawer.vue?raw';
 
const apiMocks = vi.hoisted(() => ({
  createSourcePath: vi.fn(),
  getSourceObjectFields: vi.fn(),
  getSourceObjects: vi.fn(),
  getSourcePreviewSamples: vi.fn(),
  suggestFieldCode: vi.fn(),
}));
const drawerMocks = vi.hoisted(() => ({
  changeLoading: vi.fn(),
  changeOkLoading: vi.fn(),
  closeDrawer: vi.fn(),
  init: undefined as (() => Promise<void>) | undefined,
}));
 
vi.mock('#/api/x/eln/fields', () => ({ suggestFieldCode: apiMocks.suggestFieldCode }));
vi.mock('#/api/x/eln/sources', () => apiMocks);
vi.mock('@jnpf/ui/drawer', () => ({
  BasicDrawer: {
    emits: ['ok'],
    name: 'BasicDrawer',
    template: '<aside><slot /><button data-test="drawer-ok" @click="$emit(\'ok\')">确认</button></aside>',
  },
  useDrawerInner: (init: () => Promise<void>) => {
    drawerMocks.init = init;
    return [vi.fn(), drawerMocks];
  },
}));
 
function mountDrawer() {
  return mount(SourcePathDrawer, {
    global: {
      stubs: {
        'a-alert': { props: ['message'], template: '<div>{{ message }}<slot /></div>' },
        'a-input': {
          emits: ['update:value'],
          props: ['value'],
          template: '<input :value="value" @input="$emit(\'update:value\', $event.target.value)" />',
        },
        'a-select': {
          emits: ['change'],
          props: ['options', 'value'],
          template:
            '<select :value="value" @change="$emit(\'change\', $event.target.value)"><option value=""></option><option v-for="item in options" :key="item.value" :value="item.value">{{ item.label }}</option></select>',
        },
      },
    },
  });
}
 
describe('来源路径新增抽屉', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    drawerMocks.init = undefined;
    apiMocks.getSourceObjects.mockResolvedValue({ data: [{ displayName: '检验项', id: 'task', rootAnchor: true }] });
    apiMocks.getSourceObjectFields.mockResolvedValue({ data: [{ dataType: 'DATE', displayName: '生产日期', id: 'production-date' }] });
    apiMocks.getSourcePreviewSamples.mockResolvedValue({ data: [{ id: 'sample-1', sampleName: '样品 A', testNo: 'JY001' }] });
    apiMocks.suggestFieldCode.mockResolvedValueOnce({ data: { code: 'request_date' } }).mockResolvedValueOnce({ data: { code: 'production_date' } });
    apiMocks.createSourcePath.mockResolvedValue({ data: { id: 'path-1' } });
  });
 
  it('打开时才加载元数据和校验样例', async () => {
    mountDrawer();
    expect(apiMocks.getSourceObjects).not.toHaveBeenCalled();
    expect(apiMocks.getSourcePreviewSamples).not.toHaveBeenCalled();
 
    await drawerMocks.init?.();
    await flushPromises();
 
    expect(apiMocks.getSourceObjects).toHaveBeenCalledTimes(1);
    expect(apiMocks.getSourceObjectFields).toHaveBeenCalledWith('task');
    expect(apiMocks.getSourcePreviewSamples).toHaveBeenCalledTimes(1);
  });
 
  it('校验样例加载失败时仍加载路径字段', async () => {
    apiMocks.getSourcePreviewSamples.mockRejectedValue(new Error('preview unavailable'));
    const wrapper = mountDrawer();
 
    await drawerMocks.init?.();
    await flushPromises();
 
    expect(apiMocks.getSourceObjectFields).toHaveBeenCalledWith('task');
    expect(wrapper.text()).toContain('预览检验项暂不可用,请稍后重试');
  });
 
  it('校验并发布后通知页面刷新', async () => {
    const wrapper = mountDrawer();
    await drawerMocks.init?.();
    await flushPromises();
 
    await wrapper.get('[data-test="path-display-name"]').setValue('请验单生产日期');
    await wrapper.get('[data-test="path-output-field"]').setValue('production-date');
    await wrapper.get('[data-test="path-sample"]').setValue('sample-1');
    await wrapper.get('[data-test="drawer-ok"]').trigger('click');
    await flushPromises();
 
    expect(apiMocks.createSourcePath).toHaveBeenCalledWith(
      expect.objectContaining({
        displayName: '请验单生产日期',
        outputFieldId: 'production-date',
        rootObjectId: 'task',
        sampleId: 'sample-1',
        targetObjectId: 'task',
      }),
    );
    expect(wrapper.emitted('success')).toHaveLength(1);
    expect(drawerMocks.closeDrawer).toHaveBeenCalledTimes(1);
  });
 
  it('显示完整占位提示并使用标准抽屉底部', () => {
    expect(drawerSource).toContain('placeholder="请输入路径名称,例如:请验单生产日期"');
    expect(drawerSource).toContain('placeholder="请选择到达对象"');
    expect(drawerSource).toContain('placeholder="请选择可返回的业务内容"');
    expect(drawerSource).toContain('placeholder="请选择用于校验发布的检验项"');
    expect(drawerSource).toContain('@ok="createPath"');
    expect(drawerSource).toContain('show-footer');
  });
});