material_manage_system/frontend/src/views/Application.test.js
文睿 张 fbd0bc1341 fix: 审批/取消后列表的筛选条件被丢弃
写操作后原地重新拉取列表时,status 参数被写死成 '':列表悄悄退回全量(已通过、
已拒绝的单子全冒出来),而页面下拉框仍显示着用户选中的筛选值。用户以为看到的
是筛选结果,实际不是。store 层一直有这个缺陷却没被拦住,因为页面那层没有测试。

修法照 stock.js 已有的约定(stockFilters 配合 stock.test.js 的断言):store 存一份
filters,写操作原地刷新时取出来用。

- approval.js:approve / reject 沿用筛选
- application.js:cancel 沿用筛选
- application.js:create 保持清空筛选并回第 1 页——刚提交的是待审批单,若沿用
  「已通过」之类的筛选就看不见它,用户会以为没提交成功
- Application.vue:提交成功后同步把下拉框重置为「全部」,否则 store 清了筛选而
  下拉没清,同样是表里不一

测试补 9 条(approval/application 两个 store + Application 页面层)。全部做过变异
验证:把实现改回原样后对应断言确实变红,且只有该变红的那几条变红。
2026-09-22 14:10:52 +08:00

109 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { flushPromises, mount } from '@vue/test-utils'
import ElementPlus, { ElMessage } from 'element-plus'
import { beforeEach, describe, expect, test, vi } from 'vitest'
import Application from './Application.vue'
const applicationStore = vi.hoisted(() => ({
myApplications: [],
loading: false,
myPage: { currentPage: 1, pageSize: 20, total: 0, totalPages: 0 },
fetchMyApplications: vi.fn(),
createApplication: vi.fn(),
cancelApplication: vi.fn()
}))
const materialsStore = vi.hoisted(() => ({
materialOptions: [],
fetchMaterialOptions: vi.fn()
}))
const stockStore = vi.hoisted(() => ({
fetchStock: vi.fn(),
fetchStockByMaterialId: vi.fn()
}))
vi.mock('../stores/application', () => ({ useApplicationStore: () => applicationStore }))
vi.mock('../stores/materials', () => ({ useMaterialsStore: () => materialsStore }))
vi.mock('../stores/stock', () => ({ useStockStore: () => stockStore }))
// 真实的 ElSelect 在 jsdom 下会因状态双向绑定反复触发自身更新而报
// "Maximum recursive updates exceeded"。这里用替身直接派发 change,
// 模拟用户在状态下拉里选中某一项。
const SelectStub = {
props: ['modelValue', 'placeholder', 'filterable', 'filterMethod', 'noDataText', 'disabled', 'clearable'],
emits: ['update:modelValue', 'change'],
methods: {
pick(value) {
this.$emit('update:modelValue', value)
this.$emit('change', value)
}
},
template: '<div class="select-stub"></div>'
}
const OptionStub = { props: ['label', 'value'], template: '<span />' }
function mountApplication() {
return mount(Application, {
global: {
plugins: [ElementPlus],
stubs: { teleport: true, ElSelect: SelectStub, ElOption: OptionStub }
}
})
}
// 页面里有两处 ElSelect:申请表单里的物料选择,和「我的申请」里的状态筛选。
function statusSelect(wrapper) {
return wrapper.findAllComponents(SelectStub)
.find(select => select.props('placeholder') === '全部状态')
}
function setupState(wrapper) {
return wrapper.vm.$.setupState
}
describe('提交申请后筛选条件与列表保持一致', () => {
let successSpy
beforeEach(() => {
vi.clearAllMocks()
applicationStore.createApplication.mockResolvedValue({ data: {} })
successSpy = vi.spyOn(ElMessage, 'success').mockImplementation(() => {})
})
test('状态下拉选中的值会传给列表查询', async () => {
const wrapper = mountApplication()
await flushPromises()
statusSelect(wrapper).vm.pick('approved')
await flushPromises()
expect(setupState(wrapper).statusFilter).toBe('approved')
expect(applicationStore.fetchMyApplications).toHaveBeenLastCalledWith('approved', 1)
wrapper.unmount()
})
// store 里提交后的那次刷新是刻意清空筛选的(好让刚提交的待审批单出现在列表里),
// 页面这份状态(下拉框)必须跟着一起回到「全部」:否则会出现下拉写着「已通过」、
// 列表却是全量的表里不一,这次修复就是补的这一处。
test('提交成功后下拉框的筛选要一起重置为全部', async () => {
const wrapper = mountApplication()
await flushPromises()
statusSelect(wrapper).vm.pick('approved')
await flushPromises()
expect(setupState(wrapper).statusFilter).toBe('approved')
setupState(wrapper).applyForm.purpose = '测试用途'
setupState(wrapper).applyForm.items = [
{ material_id: 7, materialSearchText: '', quantity: 1 }
]
await setupState(wrapper).handleSubmit()
await flushPromises()
expect(applicationStore.createApplication).toHaveBeenCalled()
expect(setupState(wrapper).statusFilter).toBe('')
wrapper.unmount()
})
})