diff --git a/docs/superpowers/plans/2026-10-10-material-bulk-import.md b/docs/superpowers/plans/2026-10-10-material-bulk-import.md index 97ef8fbf..c54e7d6f 100644 --- a/docs/superpowers/plans/2026-10-10-material-bulk-import.md +++ b/docs/superpowers/plans/2026-10-10-material-bulk-import.md @@ -2367,6 +2367,14 @@ git commit -m "feat: 物料导入结果弹窗组件" 在 `frontend/src/views/Materials.test.js` 末尾追加(沿用文件里已有的 `mountMaterials()`、mock 结构): ```js +describe('批量导入', () => { + beforeEach(() => { + materialsApi.importFile.mockReset() + materialsApi.downloadImportTemplate.mockReset() + materialsStore.fetchMaterials.mockReset() + vi.spyOn(ElMessage, 'success').mockImplementation(() => {}) + }) + test('批量导入成功后提示成功并刷新列表', async () => { materialsApi.importFile.mockResolvedValue({ data: { total_rows: 2, success_rows: 2, failed_rows: 0, errors: [] } @@ -2374,6 +2382,8 @@ git commit -m "feat: 物料导入结果弹窗组件" const wrapper = mountMaterials() await flushPromises() + // 挂载时 onMounted 已经拉过一次列表,清掉才能断言“导入后又拉了一次” + materialsStore.fetchMaterials.mockClear() await setupState(wrapper).handleImportFile({ target: { files: [new File(['x'], '物料.xlsx')], value: '物料.xlsx' } @@ -2381,7 +2391,7 @@ git commit -m "feat: 物料导入结果弹窗组件" await flushPromises() expect(materialsApi.importFile).toHaveBeenCalled() - expect(materialsStore.fetchMaterials).toHaveBeenCalled() + expect(materialsStore.fetchMaterials).toHaveBeenCalledWith(1, '', 'all') expect(ElMessage.success).toHaveBeenCalledWith('成功导入 2 条物料') wrapper.unmount() }) @@ -2402,6 +2412,7 @@ git commit -m "feat: 物料导入结果弹窗组件" const wrapper = mountMaterials() await flushPromises() + materialsStore.fetchMaterials.mockClear() await setupState(wrapper).handleImportFile({ target: { files: [new File(['x'], '物料.xlsx')], value: '物料.xlsx' } @@ -2412,9 +2423,19 @@ git commit -m "feat: 物料导入结果弹窗组件" expect(materialsStore.fetchMaterials).not.toHaveBeenCalled() wrapper.unmount() }) +}) ``` -**注意:** `Materials.test.js` 目前 mock 的是 `vi.mock('../stores/materials')` 与 `vi.mock('../../api/masterData')`,需要在顶部补 `vi.mock('../../api/materials')`,导出 `materialsApi`(含 `importFile`/`downloadImportTemplate` 两个 `vi.fn()`);`ElMessage` 的 spy 若尚未建立,按文件里既有的 `vi.mock('element-plus')` 方式补齐。 +**注意:** `Materials.test.js` 里已 mock 的是 `vi.mock('../stores/materials')` 与 `vi.mock('../api/masterData')`——路径相对 `src/views/`,是一级上跳。顶部要补两行(与文件里其它替身放在一起): + +```js +const materialsApi = vi.hoisted(() => ({ importFile: vi.fn(), downloadImportTemplate: vi.fn() })) +vi.mock('../api/materials', () => ({ materialsApi })) +``` + +`ElMessage` 不需要 mock 整个模块,文件里既有的写法是 `vi.spyOn(ElMessage, 'success').mockImplementation(() => {})`,新 describe 的 `beforeEach` 里照做即可。 + +**另外:** 页面 `onMounted` 就会调 `fetchMaterials()`,所以两个用例在触发导入前都要 `mockClear()`——不清的话失败用例的 `not.toHaveBeenCalled()` 必然失败,成功用例的 `toHaveBeenCalled()` 也没有区分度。 - [ ] **Step 2: 跑测试确认失败**