刘光辉
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* @vitest-environment happy-dom */
/* eslint-disable vue/one-component-per-file, vue/require-default-prop */
 
import { mount } from '@vue/test-utils';
import { defineComponent, h, nextTick } from 'vue';
 
import { describe, expect, it, vi } from 'vitest';
 
import FilePropertiesModal from '../FilePropertiesModal.vue';
 
const mocks = vi.hoisted(() => ({
  modalInit: undefined as ((data: { item: Record<string, unknown> }) => void) | undefined,
}));
 
vi.mock('@jnpf/ui/modal', async () => {
  const { defineComponent, h } = await import('vue');
  return {
    BasicModal: defineComponent({
      name: 'BasicModal',
      setup(_, { slots }) {
        return () => h('section', { 'data-test': 'basic-modal' }, slots.default?.());
      },
    }),
    useModalInner: (callback: (data: { item: Record<string, unknown> }) => void) => {
      mocks.modalInit = callback;
      return [vi.fn()];
    },
  };
});
 
const Tabs = defineComponent({
  name: 'ATabs',
  props: { activeKey: String },
  emits: ['update:activeKey'],
  setup(props, { emit, slots }) {
    return () =>
      h('div', { 'data-test': 'tabs' }, [
        h(
          'button',
          {
            'data-active': props.activeKey === 'basic',
            'data-test': 'basic-tab',
            onClick: () => emit('update:activeKey', 'basic'),
          },
          '基本信息',
        ),
        h(
          'button',
          {
            'data-active': props.activeKey === 'related',
            'data-test': 'related-tab',
            onClick: () => emit('update:activeKey', 'related'),
          },
          '相关文件',
        ),
        slots.default?.(),
      ]);
  },
});
 
const TabPane = defineComponent({
  name: 'ATabPane',
  setup(_, { slots }) {
    return () => h('section', slots.default?.());
  },
});
 
const Tag = defineComponent({
  name: 'ATag',
  setup(_, { slots }) {
    return () => h('span', slots.default?.());
  },
});
 
const Descriptions = defineComponent({
  name: 'ADescriptions',
  setup(_, { slots }) {
    return () => h('dl', { 'aria-label': '文件属性基本信息' }, slots.default?.());
  },
});
 
const DescriptionsItem = defineComponent({
  name: 'ADescriptionsItem',
  props: { label: String },
  setup(props, { slots }) {
    return () => h('div', { 'data-label': props.label }, [h('dt', props.label), h('dd', slots.default?.())]);
  },
});
 
const JnpfEmpty = defineComponent({
  name: 'JnpfEmpty',
  props: { description: String },
  setup(props) {
    return () => h('div', props.description);
  },
});
 
describe('filePropertiesModal', () => {
  it('renders file metadata and switches to the reserved related-files tab', async () => {
    const wrapper = mount(FilePropertiesModal, {
      global: {
        components: {
          'a-descriptions': Descriptions,
          'a-descriptions-item': DescriptionsItem,
          'a-tab-pane': TabPane,
          'a-tabs': Tabs,
          'a-tag': Tag,
          JnpfEmpty,
        },
      },
    });
 
    mocks.modalInit?.({
      item: {
        documentName: '清洁消毒记录',
        documentNo: 'ST-GS-04001-R02',
        effectiveFrom: '2025-06-20',
        effectiveTo: '2028-06-20',
        lifecycleStatus: 'EFFECTIVE',
        nextReviewOn: '2028-06-19',
        preparedBy: 'user-id',
        extendedProperties: { prepared_by_name: '登记制定人', reviewers: [{ user_id: 'reviewer-id', name: '文件审核人' }] },
        preparedOn: '2025-06-18',
        reviewCycleMonths: 36,
        versionLabel: 'D(02)',
      },
    });
    await nextTick();
 
    expect(wrapper.get('dl').attributes('aria-label')).toBe('文件属性基本信息');
    expect(wrapper.findAll('[data-label]').map((item) => item.attributes('data-label'))).toEqual([
      '文件编号',
      '文件名',
      '版本号',
      '制定人',
      '审核人',
      '制定日期',
      '生效时间',
      '回顾周期',
      '过期日期',
      '生命周期状态',
    ]);
    expect(wrapper.findAll('[data-label]')).toHaveLength(10);
    expect(wrapper.get('[data-label="制定人"]').text()).toContain('登记制定人');
    expect(wrapper.get('[data-label="审核人"]').text()).toContain('文件审核人');
    expect(wrapper.text()).not.toContain('user-id');
    expect(wrapper.text()).toContain('ST-GS-04001-R02');
    expect(wrapper.text()).toContain('清洁消毒记录');
    expect(wrapper.text()).toContain('2028-06-19(每 36 个月)');
    expect(wrapper.text()).toContain('已生效/执行中');
 
    await wrapper.get('[data-test="related-tab"]').trigger('click');
    expect(wrapper.get('[data-test="related-tab"]').attributes('data-active')).toBe('true');
    expect(wrapper.text()).toContain('暂无相关文件');
  });
});