|
|
|
|
@ -1,22 +1,65 @@
|
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
|
import { Button, Space, Tree, Collapse } from '@arco-design/web-react';
|
|
|
|
|
import { Button, Space, Tree, Collapse, Divider, Message } from '@arco-design/web-react';
|
|
|
|
|
import { IconLeft, IconPlus, IconEdit, IconDelete, IconLink, IconSend } from '@arco-design/web-react/icon';
|
|
|
|
|
import styles from './style/testInstance.module.less';
|
|
|
|
|
import { getComponentDesign } from '@/api/componentDevelopProcess';
|
|
|
|
|
import { getComponentTestCaseList, submitTestCase } from '@/api/componentTestCase';
|
|
|
|
|
import TestCaseModal from './TestCaseModal';
|
|
|
|
|
|
|
|
|
|
const CollapseItem = Collapse.Item;
|
|
|
|
|
|
|
|
|
|
const TestInstance = ({ instance, onBack }: { instance: any; onBack: () => void }) => {
|
|
|
|
|
const TestInstance = ({ instance, parentId, onBack }: { instance: any; parentId: string; onBack: () => void }) => {
|
|
|
|
|
const [activeTab, setActiveTab] = useState('link');
|
|
|
|
|
const [testCaseList, setTestCaseList] = useState([]);
|
|
|
|
|
const [design, setDesign] = useState(null);
|
|
|
|
|
const [modalVisible, setModalVisible] = useState(false);
|
|
|
|
|
const [selectedOperationIdent, setSelectedOperationIdent] = useState('');
|
|
|
|
|
const [activeOperationIdent, setActiveOperationIdent] = useState('');
|
|
|
|
|
|
|
|
|
|
const getDesign = async () => {
|
|
|
|
|
const res: any = await getComponentDesign(instance.id);
|
|
|
|
|
console.log('res:', res);
|
|
|
|
|
const res: any = await getComponentDesign(parentId);
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
setDesign(res.data);
|
|
|
|
|
// 默认激活第一个 operation
|
|
|
|
|
if (res.data?.operates?.length > 0) {
|
|
|
|
|
setActiveOperationIdent(res.data.operates[0].ident);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getTestCaseList = async () => {
|
|
|
|
|
const res: any = await getComponentTestCaseList({ componentBaseId: parentId, identifier: instance.identifier });
|
|
|
|
|
if (res.code === 200) setTestCaseList(res.data);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
getTestCaseList();
|
|
|
|
|
getDesign();
|
|
|
|
|
}, [instance]);
|
|
|
|
|
}, [parentId, instance]);
|
|
|
|
|
|
|
|
|
|
const handleAddTestCase = (operationIdent: string) => {
|
|
|
|
|
setSelectedOperationIdent(operationIdent);
|
|
|
|
|
setModalVisible(true);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleModalOk = async (values: any) => {
|
|
|
|
|
const params = {
|
|
|
|
|
...values,
|
|
|
|
|
componentBaseId: parentId,
|
|
|
|
|
identifier: instance.identifier
|
|
|
|
|
};
|
|
|
|
|
const res: any = await submitTestCase(params);
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
Message.success('添加测试用例成功');
|
|
|
|
|
getTestCaseList();
|
|
|
|
|
}
|
|
|
|
|
else Message.error(res.msg);
|
|
|
|
|
setModalVisible(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleModalCancel = () => {
|
|
|
|
|
setModalVisible(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles['test-instance']}>
|
|
|
|
|
@ -68,35 +111,44 @@ const TestInstance = ({ instance, onBack }: { instance: any; onBack: () => void
|
|
|
|
|
<span>测试用例</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['tree-container']}>
|
|
|
|
|
<Collapse defaultActiveKey={['1']} bordered={false}>
|
|
|
|
|
<CollapseItem header="监听组件" name="1" extra={<IconPlus />}>
|
|
|
|
|
<div className={styles['tree-list']}>
|
|
|
|
|
<div className={styles['tree-item']}>
|
|
|
|
|
<span className={styles['item-text']}>测试类型</span>
|
|
|
|
|
<div className={styles['item-actions']}>
|
|
|
|
|
<IconSend />
|
|
|
|
|
<IconEdit />
|
|
|
|
|
<IconDelete />
|
|
|
|
|
<Collapse defaultActiveKey={['1']} bordered={false} accordion>
|
|
|
|
|
{testCaseList.map((item: any, index: number) => (
|
|
|
|
|
<CollapseItem
|
|
|
|
|
header={
|
|
|
|
|
<div onClick={() => setActiveOperationIdent(item.operationIdent)}>
|
|
|
|
|
{item.operationIdent}
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
name={index.toString()}
|
|
|
|
|
key={index}
|
|
|
|
|
extra={
|
|
|
|
|
<IconPlus
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
handleAddTestCase(item.operationIdent);
|
|
|
|
|
}}
|
|
|
|
|
style={{ cursor: 'pointer' }}
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<div className={styles['tree-list']}>
|
|
|
|
|
{item.children.map((child: any, index1: number) => (
|
|
|
|
|
<div
|
|
|
|
|
className={styles['tree-item']}
|
|
|
|
|
key={index1}
|
|
|
|
|
onClick={() => setActiveOperationIdent(item.operationIdent)}
|
|
|
|
|
>
|
|
|
|
|
<span className={styles['item-text']}>{child.testCaseName}</span>
|
|
|
|
|
<div className={styles['item-actions']}>
|
|
|
|
|
<IconSend />
|
|
|
|
|
<IconEdit />
|
|
|
|
|
<IconDelete />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['tree-item']}>
|
|
|
|
|
<span className={styles['item-text']}>视频回调jck|ssss</span>
|
|
|
|
|
<div className={styles['item-actions']}>
|
|
|
|
|
<IconSend />
|
|
|
|
|
<IconEdit />
|
|
|
|
|
<IconDelete />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['tree-item']}>
|
|
|
|
|
<span className={styles['item-text']}>短剧题图识别</span>
|
|
|
|
|
<div className={styles['item-actions']}>
|
|
|
|
|
<IconSend />
|
|
|
|
|
<IconEdit />
|
|
|
|
|
<IconDelete />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</CollapseItem>
|
|
|
|
|
</CollapseItem>
|
|
|
|
|
))}
|
|
|
|
|
</Collapse>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
@ -108,7 +160,6 @@ const TestInstance = ({ instance, onBack }: { instance: any; onBack: () => void
|
|
|
|
|
<div className={styles['flow-node']}>
|
|
|
|
|
<div className={`${styles['node-box']} ${styles['node-start']}`}>
|
|
|
|
|
<div className={styles['node-header']}>
|
|
|
|
|
<span className={styles['node-icon']}>🔧</span>
|
|
|
|
|
<span className={styles['node-title']}>开始</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['node-label']}>流程协作接口</div>
|
|
|
|
|
@ -119,38 +170,56 @@ const TestInstance = ({ instance, onBack }: { instance: any; onBack: () => void
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* 组件节点 */}
|
|
|
|
|
{/* 组件节点 - 单个节点展示所有接口 */}
|
|
|
|
|
<div className={styles['flow-node']}>
|
|
|
|
|
<div className={`${styles['node-box']} ${styles['node-component']}`}>
|
|
|
|
|
<div className={styles['node-header']}>
|
|
|
|
|
<span className={styles['node-icon']}>⭐</span>
|
|
|
|
|
<span className={styles['node-title']}>计算组件#1</span>
|
|
|
|
|
<span className={styles['node-title']}>{instance.identifier}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['node-body']}>
|
|
|
|
|
<div className={styles['node-function']}>lineMove</div>
|
|
|
|
|
<div className={styles['node-function']}>circleMove</div>
|
|
|
|
|
<div className={styles['node-params']}>
|
|
|
|
|
<div className={styles['param-item']}>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
<span className={styles['param-label']}>input</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['param-item']}>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
<span className={styles['param-label']}>strpos ARR</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['param-item']}>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
<span className={styles['param-label']}>ufNum INT</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['param-item']}>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
<span className={styles['param-label']}>ufNum INT</span>
|
|
|
|
|
{/* 显示所有接口函数 - 固定在上方 */}
|
|
|
|
|
{design?.operates?.map((operation: any, index: number) => (
|
|
|
|
|
<div
|
|
|
|
|
key={index}
|
|
|
|
|
className={`${styles['node-function']} ${
|
|
|
|
|
activeOperationIdent === operation.ident ? styles['active'] : ''
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<span className={styles['function-dot']}></span>
|
|
|
|
|
{operation.ident}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['param-item-right']}>
|
|
|
|
|
<span className={styles['param-label']}>output</span>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
{/* 分割线 */}
|
|
|
|
|
<Divider />
|
|
|
|
|
|
|
|
|
|
{/* 显示激活接口的参数 */}
|
|
|
|
|
{design?.operates?.map((operation: any, index: number) => (
|
|
|
|
|
activeOperationIdent === operation.ident && (
|
|
|
|
|
<div key={index}>
|
|
|
|
|
<div className={styles['node-params']}>
|
|
|
|
|
{/* Input 参数 - 显示 parameters */}
|
|
|
|
|
{operation.parameters?.map((param: any, paramIndex: number) => (
|
|
|
|
|
<div className={`${styles['param-item']} ${styles['active']}`} key={paramIndex}>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
<span className={styles['param-label']}>
|
|
|
|
|
{param.ident} {param.type}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
{/* Output 参数 - 显示 responses */}
|
|
|
|
|
{operation.responses?.map((response: any, respIndex: number) => (
|
|
|
|
|
<div className={`${styles['param-item-right']} ${styles['active']}`} key={respIndex}>
|
|
|
|
|
<span className={styles['param-label']}>
|
|
|
|
|
{response.ident} {response.type}
|
|
|
|
|
</span>
|
|
|
|
|
<span className={styles['param-dot']}></span>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['node-connector']}>
|
|
|
|
|
@ -163,7 +232,6 @@ const TestInstance = ({ instance, onBack }: { instance: any; onBack: () => void
|
|
|
|
|
<div className={styles['flow-node']}>
|
|
|
|
|
<div className={`${styles['node-box']} ${styles['node-end']}`}>
|
|
|
|
|
<div className={styles['node-header']}>
|
|
|
|
|
<span className={styles['node-icon']}>📍</span>
|
|
|
|
|
<span className={styles['node-title']}>结束</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles['node-label']}>流程协作接口</div>
|
|
|
|
|
@ -192,6 +260,14 @@ const TestInstance = ({ instance, onBack }: { instance: any; onBack: () => void
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{modalVisible && <TestCaseModal
|
|
|
|
|
design={design.operates}
|
|
|
|
|
visible={modalVisible}
|
|
|
|
|
operationIdent={selectedOperationIdent}
|
|
|
|
|
onCancel={handleModalCancel}
|
|
|
|
|
onOk={handleModalOk}
|
|
|
|
|
/>}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|