yapi-plugin-pl-auto-test
Version:
YAPI自动化测试插件,支持在YAPI设置测试计划,历史测试结果存入ES,界面显示测试结果,自定义通知。
374 lines (344 loc) • 12.5 kB
JavaScript
import { Button, Form, Icon, Input, Radio, Switch, Tooltip } from "antd";
import { formatTime, isJson } from "client/common.js";
import PropTypes from "prop-types";
import React, { Component } from "react";
import "./index.scss";
const FormItem = Form.Item;
const { TextArea } = Input;
// layout
const formItemLayout = {
labelCol: {
lg: { span: 5 },
xs: { span: 24 },
sm: { span: 10 }
},
wrapperCol: {
lg: { span: 16 },
xs: { span: 24 },
sm: { span: 12 }
},
className: "form-item"
};
const tailFormItemLayout = {
wrapperCol: {
sm: {
span: 16,
offset: 11
}
}
};
.create()
export default class Add extends Component {
static propTypes = {
form: PropTypes.object,
planMsg: PropTypes.object,
onSubmit: PropTypes.func,
handleNameInput: PropTypes.func,
planNames: PropTypes.array
};
constructor(props) {
super(props);
this.state = {
webhook: props.planMsg.webhook,
webhook_status: props.planMsg.webhook_status,
webhook_url: props.planMsg.webhook_url,
webhook_data: props.planMsg.webhook_data ? props.planMsg.webhook_data : '{}',
auto_test_data: props.planMsg,
notifier_url: props.planMsg.notifier && props.planMsg.notifier.url
};
}
handleSubmit = async () => {
const { form, planMsg, onSubmit } = this.props;
const params = {
id: planMsg._id,
project_id: planMsg.project_id,
is_plan_open: this.state.auto_test_data.is_plan_open,
notifier_url: this.state.notifier_url,
webhook: this.state.webhook,
webhook_status: this.state.webhook_status,
webhook_url: this.state.webhook_url,
webhook_data: this.state.webhook_data
};
form.validateFields(async (err, values) => {
if (!err) {
const assignValue = Object.assign(params, values);
onSubmit(assignValue);
}
});
};
componentWillMount () {
//默认每份钟同步一次,取一个随机数
this.setState({
random_corn: `${Math.round(Math.random() * 60)} * * * *`
});
}
// 是否开启
onChange = v => {
let auto_test_data = this.state.auto_test_data;
auto_test_data.is_plan_open = v;
this.setState({
auto_test_data: auto_test_data
});
}
onHookChange = v => {
this.setState({
webhook: v
});
}
validHookData (rule, value, callback) {
if (!value) return;
value = value.trim();
if (!isJson(value)) {
callback('非法Json')
}
callback()
}
validPlanCron (rule, value, callback) {
if (!value) {
callback('Cron表达式不能为空')
}
value = value.trim();
const varArr = value.split(" ")
if (varArr.length > 5) {
callback('当前只支持分钟级定时, 请确认表达式分割后为5位')
}
callback()
}
validHookUrl (rule, value, callback) {
if (!value) {
callback('Url不能为空')
}
value = value.trim();
if (!value.includes("http") && !value.includes("https")) {
callback('非法Url')
}
callback()
}
onTriggerChange = v => {
let auto_test_data = this.state.auto_test_data;
auto_test_data.notice_trigger = v;
this.setState({
auto_test_data: auto_test_data
});
}
// 打开一个新窗口执行一次计划
runPlan = () => {
const { form } = this.props;
form.validateFields(async (err, values) => {
if (!err) {
window.open(values.plan_url, "_blank");
}
});
}
render () {
const { planNames, planMsg } = this.props;
const { getFieldDecorator } = this.props.form;
const trigger = this.state.auto_test_data.notice_trigger;
if (trigger === "fail" || trigger === "part") {
this.state.auto_test_data.notice_trigger = "existFail"
};
return (
<div className="m-panel">
<Form>
<FormItem
label="是否执行测试计划"
{...formItemLayout}
>
<Switch
checked={this.state.auto_test_data.is_plan_open}
onChange={this.onChange}
checkedChildren="开"
unCheckedChildren="关"
/>
{planMsg._id ? (<Button
type="primary"
icon="play-circle"
className="run-once"
onClick={this.runPlan}
>
执行一次
</Button>) : null}
{this.state.auto_test_data.last_test_time != null
? (<div>上次执行时间: <span className="testtime">{formatTime(this.state.auto_test_data.last_test_time)}</span></div>) : null}
</FormItem>
<div>
<FormItem {...formItemLayout} label="计划名称">
{getFieldDecorator("plan_name", {
rules: [
{
required: true,
message: "请输入计划名称"
},
{
validator: (rule, value, callback) => {
if (value) {
if (planNames.includes(value)) {
callback("计划名称重复");
} else if (!/\S/.test(value)) {
callback("请输入计划名称");
} else {
callback();
}
} else {
callback("请输入计划名称");
}
}
}
],
validateTrigger: "onBlur",
initialValue: this.state.auto_test_data._id === 0 ? "" : this.state.auto_test_data.plan_name
})(<Input onChange={e => this.props.handleNameInput(e.target.value)} />)}
</FormItem>
<FormItem {...formItemLayout}
label={
<span>
自动测试URL
<Tooltip title="复制测试集合服务端测试的URL">
<Icon type="question-circle-o" />
</Tooltip>
</span>
}>
{getFieldDecorator("plan_url", {
rules: [
{
required: true,
message: "请输入服务器端自动测试URL"
}
],
validateTrigger: "onBlur",
initialValue: this.state.auto_test_data.plan_url
})(<Input />)}
</FormItem>
<FormItem {...formItemLayout} label={<span>类cron风格表达式 <a href="https://github.com/node-schedule/node-schedule">GitHub</a></span>}>
{getFieldDecorator("plan_cron", {
rules: [
{
required: true,
message: "请输入node-schedule的类cron表达式!"
},
{
validator: this.validPlanCron
}
],
initialValue: this.state.auto_test_data.plan_cron
? this.state.auto_test_data.plan_cron : this.state.random_corn
})(<Input />)}
</FormItem>
<FormItem {...formItemLayout} label={
<span>
保留测试结果数,-1为不限
<Tooltip title="配置影响每个测试计划保留的测试结果数,设置为-1表示不限,下次执行生效">
<Icon type="question-circle-o" />
</Tooltip>
</span>
}>
{getFieldDecorator("plan_result_size", {
rules: [
{
required: true,
message: "请输入保留次数"
}, {
validator: (rule, value, callback) => {
if (value !== "") {
if (!/^\d+$/.test(value) && value != -1) {
callback("请输入非负整数或-1");
} else {
callback();
}
} else {
callback("请输入保留次数");
}
}
}
],
validateTrigger: "onBlur",
initialValue: this.state.auto_test_data.plan_result_size
})(<Input />)}
</FormItem>
<FormItem {...formItemLayout} label="触发通知">
{getFieldDecorator("notice_trigger", {
initialValue: this.state.auto_test_data.notice_trigger || "never"
})(
<Radio.Group onChange={this.onTriggerChange}>
<Radio value="any">执行结束</Radio>
<Radio value="never">不发送</Radio>
<Radio value="success">全部通过</Radio>
<Radio value="existFail">存在失败</Radio>
</Radio.Group>
)}
</FormItem>
{/* <FormItem {...formItemLayout} label="类型通知">
{getFieldDecorator("notice_client", {
initialValue: "workWX"
})(
<Radio.Group onChange={this.onChange}>
<Radio value="email">邮箱</Radio>
<Radio value="workWX">企业微信</Radio>
</Radio.Group>
)}
</FormItem> */}
<FormItem {...formItemLayout} label={<span>企业微信机器人URL <a href="https://work.weixin.qq.com/api/doc/90000/90136/91770">文档</a></span>}>
{getFieldDecorator("notifier_url", {
initialValue: this.state.notifier_url
})(<Input />)}
</FormItem>
<FormItem
label="WebHook"
{...formItemLayout}
>
<Switch
checked={this.state.webhook}
onChange={this.onHookChange}
checkedChildren="开"
unCheckedChildren="关"
/>
{this.state.webhook
? (<div>上次发送状态: <span className="testtime">{this.state.webhook_status}</span></div>) : null}
</FormItem>
{this.state.webhook ? (<div>
<FormItem {...formItemLayout} label="Url">
{getFieldDecorator("webhook_url", {
rules: [
{
required: true
},
{
validator: this.validHookUrl
}
],
validateTrigger: "onBlur",
initialValue: this.state.webhook_url
})(<Input />)}
</FormItem>
<FormItem {...formItemLayout} label={
<span>
PostData
<Tooltip title='发送自定义post数据,自动增加yapi执行结果{"yapi":{"planName":"a"},"status":"b","failedCases":["a","b"],"detail":"http://aa"}}'>
<Icon type="question-circle-o" />
</Tooltip>
</span>
}>
{getFieldDecorator('webhook_data', {
rules: [
{
required: false
},
{
validator: this.validHookData
}
],
validateTrigger: "onBlur",
initialValue: this.state.webhook_data
})(<TextArea rows={4} placeholder="请输入json,yapi会在发出时,增加以yapi为key的post数据" />)}
</FormItem></div>) : null}
</div>
<FormItem {...tailFormItemLayout}>
<Button type="primary" htmlType="submit" icon="save" size="large" onClick={this.handleSubmit}>
保存
</Button>
</FormItem>
</Form>
</div>
);
}
}