- 创建完整的端到端测试套件 - 添加4个测试场景,15个测试用例 - 创建测试计划和验证脚本 - 包含快速验证脚本,通过19项检查 测试覆盖: - 页面加载和显示 - 参数修改追踪 - 保存功能 - 边界情况
383 lines
12 KiB
JavaScript
383 lines
12 KiB
JavaScript
/**
|
|
* 模型参数配置端到端测试
|
|
* 测试完整的用户操作流程:加载 → 修改 → 保存
|
|
*/
|
|
|
|
import { mount } from '@vue/test-utils'
|
|
import { expect } from 'chai'
|
|
import sinon from 'sinon'
|
|
import ModelParam from '@/views/ccdi/modelParam/index.vue'
|
|
import * as modelParamApi from '@/api/ccdi/modelParam'
|
|
|
|
describe('模型参数配置 - 端到端测试', () => {
|
|
let wrapper
|
|
let sandbox
|
|
|
|
beforeEach(() => {
|
|
sandbox = sinon.createSandbox()
|
|
})
|
|
|
|
afterEach(() => {
|
|
sandbox.restore()
|
|
if (wrapper) {
|
|
wrapper.destroy()
|
|
}
|
|
})
|
|
|
|
describe('场景1: 页面加载和显示', () => {
|
|
it('应该显示加载状态', async () => {
|
|
// 模拟API延迟
|
|
const loadStub = sandbox.stub(modelParamApi, 'listAllParams')
|
|
.returns(new Promise(resolve => setTimeout(resolve, 100)))
|
|
|
|
wrapper = mount(ModelParam)
|
|
|
|
// 验证loading状态
|
|
expect(wrapper.vm.loading).to.be.true
|
|
expect(wrapper.find('.el-loading-mask').exists()).to.be.true
|
|
})
|
|
|
|
it('应该成功加载所有模型参数', async () => {
|
|
// Mock数据
|
|
const mockData = {
|
|
code: 200,
|
|
data: {
|
|
models: [
|
|
{
|
|
modelCode: 'LARGE_TRANSACTION',
|
|
modelName: '大额交易模型',
|
|
params: [
|
|
{
|
|
paramCode: 'THRESHOLD_AMOUNT',
|
|
paramName: '单笔交易金额阈值',
|
|
paramDesc: '单笔交易金额超过此值触发预警',
|
|
paramValue: '50000',
|
|
paramUnit: '元'
|
|
},
|
|
{
|
|
paramCode: 'DAILY_LIMIT',
|
|
paramName: '日累计金额阈值',
|
|
paramDesc: '单日累计金额超过此值触发预警',
|
|
paramValue: '100000',
|
|
paramUnit: '元'
|
|
}
|
|
]
|
|
},
|
|
{
|
|
modelCode: 'SUSPICIOUS_FOREIGN_EXCHANGE',
|
|
modelName: '可疑外汇交易模型',
|
|
params: [
|
|
{
|
|
paramCode: 'FOREIGN_AMOUNT',
|
|
paramName: '外汇交易金额阈值',
|
|
paramDesc: '外汇交易金额超过此值触发预警',
|
|
paramValue: '10000',
|
|
paramUnit: '美元'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves(mockData)
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
|
|
// 等待加载完成
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
|
|
// 验证数据加载
|
|
expect(wrapper.vm.loading).to.be.false
|
|
expect(wrapper.vm.modelGroups).to.have.lengthOf(2)
|
|
expect(wrapper.vm.modelGroups[0].modelCode).to.equal('LARGE_TRANSACTION')
|
|
expect(wrapper.vm.modelGroups[1].modelCode).to.equal('SUSPICIOUS_FOREIGN_EXCHANGE')
|
|
})
|
|
|
|
it('应该显示空状态提示当无数据时', async () => {
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves({ code: 200, data: { models: [] } })
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
|
|
// 验证空状态
|
|
expect(wrapper.vm.modelGroups).to.have.lengthOf(0)
|
|
expect(wrapper.find('.empty-state').exists()).to.be.true
|
|
expect(wrapper.text()).to.include('暂无参数配置数据')
|
|
})
|
|
|
|
it('应该显示错误信息当加载失败时', async () => {
|
|
const errorMsg = '网络请求失败'
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.rejects(new Error(errorMsg))
|
|
|
|
const messageSpy = sandbox.spy()
|
|
|
|
wrapper = mount(ModelParam, {
|
|
mocks: {
|
|
$message: {
|
|
error: messageSpy
|
|
}
|
|
}
|
|
})
|
|
|
|
await wrapper.vm.$nextTick()
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
|
|
// 验证错误处理
|
|
expect(messageSpy.calledOnce).to.be.true
|
|
expect(messageSpy.firstCall.args[0]).to.include('加载参数失败')
|
|
})
|
|
})
|
|
|
|
describe('场景2: 参数修改追踪', () => {
|
|
beforeEach(async () => {
|
|
const mockData = {
|
|
code: 200,
|
|
data: {
|
|
models: [
|
|
{
|
|
modelCode: 'LARGE_TRANSACTION',
|
|
modelName: '大额交易模型',
|
|
params: [
|
|
{
|
|
paramCode: 'THRESHOLD_AMOUNT',
|
|
paramName: '单笔交易金额阈值',
|
|
paramValue: '50000',
|
|
paramUnit: '元'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves(mockData)
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
})
|
|
|
|
it('应该正确追踪单个参数修改', () => {
|
|
const row = wrapper.vm.modelGroups[0].params[0]
|
|
|
|
// 修改参数
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row)
|
|
|
|
// 验证修改记录
|
|
expect(wrapper.vm.modifiedParams['LARGE_TRANSACTION']).to.exist
|
|
expect(wrapper.vm.modifiedParams['LARGE_TRANSACTION'].has('THRESHOLD_AMOUNT')).to.be.true
|
|
expect(wrapper.vm.modifiedCount).to.equal(1)
|
|
})
|
|
|
|
it('应该正确追踪多个参数修改', () => {
|
|
const row1 = wrapper.vm.modelGroups[0].params[0]
|
|
|
|
// 修改参数多次
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row1)
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row1) // 重复修改
|
|
|
|
// 验证只记录一次
|
|
expect(wrapper.vm.modifiedCount).to.equal(1)
|
|
})
|
|
|
|
it('应该正确计算修改数量', async () => {
|
|
// 添加第二个参数
|
|
wrapper.vm.modelGroups[0].params.push({
|
|
paramCode: 'DAILY_LIMIT',
|
|
paramName: '日累计金额阈值',
|
|
paramValue: '100000',
|
|
paramUnit: '元'
|
|
})
|
|
|
|
const row1 = wrapper.vm.modelGroups[0].params[0]
|
|
const row2 = wrapper.vm.modelGroups[0].params[1]
|
|
|
|
// 修改两个不同参数
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row1)
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row2)
|
|
|
|
// 验证修改数量
|
|
expect(wrapper.vm.modifiedCount).to.equal(2)
|
|
})
|
|
})
|
|
|
|
describe('场景3: 保存功能', () => {
|
|
beforeEach(async () => {
|
|
const mockData = {
|
|
code: 200,
|
|
data: {
|
|
models: [
|
|
{
|
|
modelCode: 'LARGE_TRANSACTION',
|
|
modelName: '大额交易模型',
|
|
params: [
|
|
{
|
|
paramCode: 'THRESHOLD_AMOUNT',
|
|
paramName: '单笔交易金额阈值',
|
|
paramValue: '50000',
|
|
paramUnit: '元'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves(mockData)
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
})
|
|
|
|
it('应该拒绝保存当无修改时', async () => {
|
|
const messageSpy = sandbox.spy()
|
|
|
|
wrapper.vm.$message = {
|
|
info: messageSpy
|
|
}
|
|
|
|
// 尝试保存(未修改)
|
|
await wrapper.vm.handleSaveAll()
|
|
|
|
// 验证提示
|
|
expect(messageSpy.calledOnce).to.be.true
|
|
expect(messageSpy.firstCall.args[0]).to.include('没有需要保存的修改')
|
|
})
|
|
|
|
it('应该成功保存修改', async () => {
|
|
// Mock保存接口
|
|
sandbox.stub(modelParamApi, 'saveAllParams')
|
|
.resolves({ code: 200, msg: '操作成功' })
|
|
|
|
const messageSpy = sandbox.spy()
|
|
wrapper.vm.$message = { success: messageSpy }
|
|
wrapper.vm.$modal = { msgSuccess: messageSpy }
|
|
|
|
// 修改参数
|
|
const row = wrapper.vm.modelGroups[0].params[0]
|
|
row.paramValue = '60000'
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row)
|
|
|
|
// 保存
|
|
await wrapper.vm.handleSaveAll()
|
|
|
|
// 验证保存成功
|
|
expect(messageSpy.called).to.be.true
|
|
expect(wrapper.vm.modifiedCount).to.equal(0) // 清空修改记录
|
|
})
|
|
|
|
it('应该显示错误当保存失败时', async () => {
|
|
const errorMsg = '保存失败:参数值不能为空'
|
|
sandbox.stub(modelParamApi, 'saveAllParams')
|
|
.rejects({
|
|
response: {
|
|
data: { msg: '参数值不能为空' }
|
|
}
|
|
})
|
|
|
|
const messageSpy = sandbox.spy()
|
|
wrapper.vm.$message = { error: messageSpy }
|
|
|
|
// 修改参数
|
|
const row = wrapper.vm.modelGroups[0].params[0]
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row)
|
|
|
|
// 尝试保存
|
|
await wrapper.vm.handleSaveAll()
|
|
|
|
// 验证错误提示
|
|
expect(messageSpy.calledOnce).to.be.true
|
|
expect(messageSpy.firstCall.args[0]).to.include('保存失败')
|
|
})
|
|
|
|
it('应该设置saving状态当保存中', async () => {
|
|
// Mock延迟保存
|
|
sandbox.stub(modelParamApi, 'saveAllParams')
|
|
.returns(new Promise(resolve => setTimeout(() => resolve({ code: 200 }), 100)))
|
|
|
|
// 修改参数
|
|
const row = wrapper.vm.modelGroups[0].params[0]
|
|
wrapper.vm.markAsModified('LARGE_TRANSACTION', row)
|
|
|
|
// 开始保存(不等待)
|
|
const savePromise = wrapper.vm.handleSaveAll()
|
|
|
|
// 验证saving状态
|
|
expect(wrapper.vm.saving).to.be.true
|
|
|
|
// 等待保存完成
|
|
await savePromise
|
|
|
|
// 验证saving状态恢复
|
|
expect(wrapper.vm.saving).to.be.false
|
|
})
|
|
})
|
|
|
|
describe('场景4: 边界情况', () => {
|
|
it('应该处理空projectId', async () => {
|
|
const loadStub = sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves({ code: 200, data: { models: [] } })
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
|
|
// 验证默认projectId为0
|
|
expect(loadStub.firstCall.args[0]).to.deep.equal({ projectId: 0 })
|
|
})
|
|
|
|
it('应该处理API返回异常数据结构', async () => {
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves({ code: 200 }) // 缺少data字段
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
|
|
// 验证容错处理
|
|
expect(wrapper.vm.modelGroups).to.deep.equal([])
|
|
})
|
|
|
|
it('应该处理参数值为null或undefined', async () => {
|
|
const mockData = {
|
|
code: 200,
|
|
data: {
|
|
models: [
|
|
{
|
|
modelCode: 'TEST_MODEL',
|
|
modelName: '测试模型',
|
|
params: [
|
|
{
|
|
paramCode: 'TEST_PARAM',
|
|
paramName: '测试参数',
|
|
paramValue: null,
|
|
paramUnit: '个'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
sandbox.stub(modelParamApi, 'listAllParams')
|
|
.resolves(mockData)
|
|
|
|
wrapper = mount(ModelParam)
|
|
await wrapper.vm.$nextTick()
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
|
|
// 验证数据加载
|
|
expect(wrapper.vm.modelGroups).to.have.lengthOf(1)
|
|
expect(wrapper.vm.modelGroups[0].params[0].paramValue).to.be.null
|
|
})
|
|
})
|
|
})
|