feat(componentTest): 新增测试用例配置弹窗组件
parent
bba9318e9d
commit
f9e7a55b96
@ -0,0 +1,180 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Modal, Form, Input, Button, Select, Space } from '@arco-design/web-react';
|
||||||
|
import styles from './style/testCaseModal.module.less';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
const Option = Select.Option;
|
||||||
|
|
||||||
|
interface TestCaseModalProps {
|
||||||
|
design: Record<string, any>;
|
||||||
|
visible: boolean;
|
||||||
|
operationIdent: string;
|
||||||
|
onCancel: () => void;
|
||||||
|
onOk: (values: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dict = [
|
||||||
|
{
|
||||||
|
label: '通过用例',
|
||||||
|
value: '通过用例'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '失败用例',
|
||||||
|
value: '失败用例'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '参数有误',
|
||||||
|
value: '参数有误'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '数据为空',
|
||||||
|
value: '数据为空'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '缺少参数',
|
||||||
|
value: '缺少参数'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '记录不存在',
|
||||||
|
value: '记录不存在'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const TestCaseModal: React.FC<TestCaseModalProps> = ({ design, visible, operationIdent, onCancel, onOk }) => {
|
||||||
|
const [testCaseFunctions, setTestCaseFunctions] = useState(null);
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
const formValues = await form.validate();
|
||||||
|
|
||||||
|
// 构造完整的数据结构,包含原始字段信息和用户输入的值
|
||||||
|
const result = {
|
||||||
|
testCaseName: formValues.testCaseName,
|
||||||
|
operation: operationIdent,
|
||||||
|
expectDataIns: testCaseFunctions.parameters.map((param, index) => ({
|
||||||
|
ident: param.ident,
|
||||||
|
type: param.type,
|
||||||
|
generic: param.generic,
|
||||||
|
desc: param.desc,
|
||||||
|
// 用户输入的值
|
||||||
|
value: formValues[`parameters_${index}`] || ''
|
||||||
|
})),
|
||||||
|
expectDataOuts: testCaseFunctions.responses.map((resp, index) => ({
|
||||||
|
ident: resp.ident,
|
||||||
|
type: resp.type,
|
||||||
|
generic: resp.generic,
|
||||||
|
desc: resp.desc,
|
||||||
|
// 用户输入的值
|
||||||
|
value: formValues[`responses_${index}`] || ''
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
onOk(result);
|
||||||
|
form.resetFields();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
form.resetFields();
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTestCaseFunctions(design.find(item => item.ident === operationIdent));
|
||||||
|
}, [visible, operationIdent, design]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="配置测试用例"
|
||||||
|
visible={visible}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
autoFocus={false}
|
||||||
|
focusLock={true}
|
||||||
|
style={{ width: 1000 }}
|
||||||
|
footer={
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '12px' }}>
|
||||||
|
<Button onClick={handleCancel}>取消</Button>
|
||||||
|
<Button type="primary" onClick={handleOk}>
|
||||||
|
确定
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={styles['modal-content']}>
|
||||||
|
<div className={styles['modal-header']}>
|
||||||
|
<span className={styles['header-label']}>接口:</span>
|
||||||
|
<span className={styles['header-value']}>{operationIdent}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Form form={form} layout="vertical" autoComplete="off">
|
||||||
|
<FormItem
|
||||||
|
label="用例名称"
|
||||||
|
field="testCaseName"
|
||||||
|
rules={[{ required: true, message: '请输入用例名称' }]}
|
||||||
|
>
|
||||||
|
<Select placeholder="请输入或选择测试用例" allowCreate allowClear>
|
||||||
|
{dict.map((option, index) => (
|
||||||
|
<Option key={index} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<div className={styles['section-title']}>输入参数:</div>
|
||||||
|
<div className={styles['params-table']}>
|
||||||
|
<div className={styles['table-header']}>
|
||||||
|
<div className={styles['col-index']}></div>
|
||||||
|
<div className={styles['col-name']}>名称</div>
|
||||||
|
<div className={styles['col-param-type']}>参数类型</div>
|
||||||
|
<div className={styles['col-data-type']}>数据类型</div>
|
||||||
|
<div className={styles['col-value']}>参数值</div>
|
||||||
|
</div>
|
||||||
|
{testCaseFunctions && testCaseFunctions.parameters.map((item, index) => (
|
||||||
|
<div className={styles['table-row']} key={index}>
|
||||||
|
<div className={styles['col-index']}>{index + 1}</div>
|
||||||
|
<div className={styles['col-name']}>{item.ident}</div>
|
||||||
|
<div className={styles['col-param-type']}>{item.type}</div>
|
||||||
|
<div className={styles['col-data-type']}>{item.generic || '-'}</div>
|
||||||
|
<div className={styles['col-value']}>
|
||||||
|
<FormItem field={`parameters_${index}`} noStyle>
|
||||||
|
<Input placeholder="请输入参数值" />
|
||||||
|
</FormItem>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles['section-title']}>输出参数:</div>
|
||||||
|
<div className={styles['params-table']}>
|
||||||
|
<div className={styles['table-header']}>
|
||||||
|
<div className={styles['col-index']}></div>
|
||||||
|
<div className={styles['col-name']}>名称</div>
|
||||||
|
<div className={styles['col-param-type']}>参数类型</div>
|
||||||
|
<div className={styles['col-data-type']}>数据类型</div>
|
||||||
|
<div className={styles['col-value']}>参数值</div>
|
||||||
|
</div>
|
||||||
|
{testCaseFunctions && testCaseFunctions.responses.map((item, index) => (
|
||||||
|
<div className={styles['table-row']} key={index}>
|
||||||
|
<div className={styles['col-index']}>{index + 1}</div>
|
||||||
|
<div className={styles['col-name']}>{item.ident}</div>
|
||||||
|
<div className={styles['col-param-type']}>{item.type}</div>
|
||||||
|
<div className={styles['col-data-type']}>{item.generic || '-'}</div>
|
||||||
|
<div className={styles['col-value']}>
|
||||||
|
<FormItem field={`responses_${index}`} noStyle>
|
||||||
|
<Input placeholder="请输入参数值" />
|
||||||
|
</FormItem>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TestCaseModal;
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
.modal-content {
|
||||||
|
padding: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.header-label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #1d2129;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-value {
|
||||||
|
color: #4080ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1d2129;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-table {
|
||||||
|
border: 1px solid #e5e6eb;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
border-bottom: 1px solid #e5e6eb;
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #4e5969;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid #e5e6eb;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-index {
|
||||||
|
width: 40px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #86909c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-name {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-param-type {
|
||||||
|
width: 120px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 12px;
|
||||||
|
color: #4e5969;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-data-type {
|
||||||
|
width: 100px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 12px;
|
||||||
|
color: #4e5969;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-value {
|
||||||
|
flex: 2;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue