UNPKG

yapi-plugin-pl-auto-test

Version:

YAPI自动化测试插件,支持在YAPI设置测试计划,历史测试结果存入ES,界面显示测试结果,自定义通知。

374 lines (344 loc) 12.5 kB
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 } } }; @Form.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&nbsp; <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风格表达式&nbsp;<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为不限&nbsp; <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&nbsp;<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&nbsp; <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> ); } }