opti: postman 交互

This commit is contained in:
suxiaoxin 2017-09-22 10:58:50 +08:00
parent 49c9178ea2
commit 38d4e360dd
4 changed files with 118 additions and 50 deletions

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Mock from 'mockjs'
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Tooltip, message } from 'antd'
import { Button, Input, Select, Card, Alert, Spin, Icon, Collapse, Tooltip, message, AutoComplete } from 'antd'
import { autobind } from 'core-decorators';
import constants from '../../constants/variable.js'
@ -20,7 +20,6 @@ function json_parse(data) {
}
}
function isJsonData(headers) {
if (!headers || typeof headers !== 'object') return false;
let isResJson = false;
@ -32,6 +31,15 @@ function isJsonData(headers) {
return isResJson;
}
const wordList = constants.MOCK_SOURCE;
const mockDataSource = wordList.map(item => {
return <AutoComplete.Option key={item.mock} value={item.mock}>
{item.mock}&nbsp; &nbsp;随机{item.name}
</AutoComplete.Option>
});
const { TextArea } = Input;
const InputGroup = Input.Group;
const Option = Select.Option;
@ -127,7 +135,7 @@ export default class Run extends Component {
test_status = '',
test_res_body = '',
test_report = [],
test_res_header=''
test_res_header = ''
} = data;
// case 任意编辑 pathname不管项目的 basepath
@ -169,12 +177,12 @@ export default class Run extends Component {
if (req_body_type && req_body_type !== 'file' && req_body_type !== 'form') {
this.loadBodyEditor()
}
if(test_res_body){
if (test_res_body) {
this.bindAceEditor();
}
});
}
@autobind
@ -278,9 +286,8 @@ export default class Run extends Component {
}
@autobind
changeHeader(e, index, isName) {
changeHeader(v, index, isName) {
const headers = json_parse(JSON.stringify(this.state.headers));
const v = e.target.value;
if (isName) {
headers[index].name = v;
} else {
@ -306,9 +313,8 @@ export default class Run extends Component {
}
@autobind
changeQuery(e, index, isKey) {
changeQuery(v, index, isKey) {
const query = json_parse(JSON.stringify(this.state.query));
const v = e.target.value;
if (isKey) {
query[index].name = v;
} else {
@ -328,9 +334,8 @@ export default class Run extends Component {
}
@autobind
changePathParam(e, index, isKey) {
changePathParam(v, index, isKey) {
const pathParam = JSON.parse(JSON.stringify(this.state.pathParam));
const v = e.target.value;
const name = pathParam[index].name;
let newPathname = this.state.pathname;
if (isKey) {
@ -359,27 +364,12 @@ export default class Run extends Component {
}
@autobind
changeBody(e, index, type) {
changeBody(v, index) {
const bodyForm = json_parse(JSON.stringify(this.state.bodyForm));
switch (type) {
case 'key':
bodyForm[index].name = e.target.value
break;
case 'type':
bodyForm[index].type = e
break;
case 'value':
if (bodyForm[index].type === 'file') {
bodyForm[index].value = e.target.id
} else {
bodyForm[index].value = e.target.value
}
break;
default:
break;
}
if (type === 'type' && e === 'file') {
//this.setContentType('multipart/form-data')
if (bodyForm[index].type === 'file') {
bodyForm[index].value = 'file_' + index
} else {
bodyForm[index].value = v
}
this.setState({ bodyForm });
}
@ -603,7 +593,14 @@ export default class Run extends Component {
<div key={index} className="key-value-wrap">
<Input disabled value={item.name} onChange={e => this.changePathParam(e, index, true)} className="key" />
<span className="eq-symbol">=</span>
<Input value={item.value} onChange={e => this.changePathParam(e, index)} className="value" />
<AutoComplete
value={item.value}
onChange={e => this.changePathParam(e, index)}
className="value"
dataSource={mockDataSource}
placeholder="参数值"
optionLabelProp="value"
/>
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deletePathParam(index)} />
</div>
)
@ -618,7 +615,14 @@ export default class Run extends Component {
<div key={index} className="key-value-wrap">
<Input disabled value={item.name} onChange={e => this.changeQuery(e, index, true)} className="key" />
<span className="eq-symbol">=</span>
<Input value={item.value} onChange={e => this.changeQuery(e, index)} className="value" />
<AutoComplete
value={item.value}
onChange={e => this.changeQuery(e, index)}
className="value"
dataSource={mockDataSource}
placeholder="参数值"
optionLabelProp="value"
/>
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteQuery(index)} />
</div>
)
@ -633,7 +637,14 @@ export default class Run extends Component {
<div key={index} className="key-value-wrap">
<Input disabled value={item.name} onChange={e => this.changeHeader(e, index, true)} className="key" />
<span className="eq-symbol">=</span>
<Input value={item.value} onChange={e => this.changeHeader(e, index)} className="value" />
<AutoComplete
value={item.value}
onChange={e => this.changeHeader(e, index)}
className="value"
dataSource={mockDataSource}
placeholder="参数值"
optionLabelProp="value"
/>
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteHeader(index)} />
</div>
)
@ -662,7 +673,7 @@ export default class Run extends Component {
bodyForm.map((item, index) => {
return (
<div key={index} className="key-value-wrap">
<Input disabled value={item.name} onChange={e => this.changeBody(e, index, 'key')} className="key" />
<Input disabled value={item.name} onChange={e => this.changeBody(e, index, 'key')} className="key" />
<span>[</span>
<Select disabled value={item.type} onChange={e => this.changeBody(e, index, 'type')}>
<Option value="file">File</Option>
@ -672,7 +683,15 @@ export default class Run extends Component {
<span className="eq-symbol">=</span>
{item.type === 'file' ?
<Input type="file" id={'file_' + index} onChange={e => this.changeBody(e, index, 'value')} multiple className="value" /> :
<Input value={item.value} onChange={e => this.changeBody(e, index, 'value')} className="value" />
<AutoComplete
value={item.value}
onChange={e => this.changeBody(e, index, 'value')}
className="value"
dataSource={mockDataSource}
placeholder="参数值"
optionLabelProp="value"
/>
}
<Icon style={{ display: 'none' }} type="delete" className="icon-btn" onClick={() => this.deleteBody(index)} />
</div>

View File

@ -115,5 +115,53 @@ export default {
bac: "#fff3cf",
color: "#ffbf00"
}
}
},
MOCK_SOURCE: [
{ name: '字符串', mock: '@string' },
{ name: '自然数', mock: '@natural' },
{ name: '浮点数', mock: '@float' },
{ name: '字符', mock: '@character' },
{ name: '布尔', mock: '@boolean' },
{ name: 'url', mock: '@url' },
{ name: '域名', mock: '@domain' },
{ name: 'ip地址', mock: '@ip' },
{ name: 'id', mock: '@id' },
{ name: 'guid', mock: '@guid' },
{ name: '当前时间', mock: '@now' },
{ name: '日期', mock: '@date' },
{ name: '时间', mock: '@time' },
{ name: '日期时间', mock: '@datetime' },
{ name: '图片连接', mock: '@image' },
{ name: '图片data', mock: "@imageData" },
{ name: '颜色', mock: '@color' },
{ name: '颜色hex', mock: '@hex' },
{ name: '颜色rgba', mock: '@rgba' },
{ name: '颜色rgb', mock: '@rgb' },
{ name: '颜色hsl', mock: '@hsl' },
{ name: '整数', mock: '@integer' },
{ name: 'email', mock: '@email' },
{ name: '大段文本', mock: '@paragraph' },
{ name: '句子', mock: '@sentence' },
{ name: '单词', mock: '@word' },
{ name: '大段中文文本', mock: '@cparagraph' },
{ name: '中文标题', mock: '@ctitle' },
{ name: '标题', mock: '@title' },
{ name: '姓名', mock: '@name' },
{ name: '中文姓名', mock: '@cname' },
{ name: '中文姓', mock: '@cfirst' },
{ name: '中文名', mock: '@clast' },
{ name: '英文姓', mock: '@first' },
{ name: '英文名', mock: '@last' },
{ name: '中文句子', mock: '@csentence' },
{ name: '中文词组', mock: '@cword' },
{ name: '地址', mock: '@region' },
{ name: '省份', mock: '@province' },
{ name: '城市', mock: '@city' },
{ name: '地区', mock: '@county' },
{ name: '转换为大写', mock: '@upper' },
{ name: '转换为小写', mock: '@lower' },
{ name: '挑选(枚举)', mock: '@pick' },
{ name: '打乱数组', mock: '@shuffle' },
{ name: '协议', mock: '@protocol' }
]
}

View File

@ -187,7 +187,7 @@ class InterfaceColContent extends Component {
if (validRes.length === 0) {
result.code = 0;
result.validRes = [{message: '验证通过'}];
result.validRes = [{ message: '验证通过' }];
resolve(result);
} else if (validRes.length > 0) {
result.code = 1;
@ -207,23 +207,23 @@ class InterfaceColContent extends Component {
})
}
handleVarWord(val){
handleVarWord(val) {
return simpleJsonPathParse(val, this.records)
}
handleValue(val){
if(!val || typeof val !== 'string'){
handleValue(val) {
if (!val || typeof val !== 'string') {
return val;
}else if(val[0] === '@'){
} else if (val[0] === '@') {
return handleMockWord(val);
}else if(val.indexOf('$.') === 0){
} else if (val.indexOf('$.') === 0) {
return this.handleVarWord(val);
}
return val;
}
arrToObj =(arr) =>{
arrToObj = (arr) => {
arr = arr || [];
const obj = {};
arr.forEach(item => {
@ -234,7 +234,7 @@ class InterfaceColContent extends Component {
return obj;
}
getQueryObj =(query)=> {
getQueryObj = (query) => {
query = query || [];
const queryObj = {};
query.forEach(item => {
@ -244,7 +244,7 @@ class InterfaceColContent extends Component {
})
return queryObj;
}
getHeadersObj = (headers) =>{
getHeadersObj = (headers) => {
headers = headers || [];
const headersObj = {};
headers.forEach(item => {
@ -409,7 +409,9 @@ class InterfaceColContent extends Component {
return (
<div className="interface-col">
<h2 style={{ marginBottom: '10px', display: 'inline-block' }}>测试集合</h2>
<h2 style={{ marginBottom: '10px', display: 'inline-block' }}>测试集合&nbsp;<a target="_blank" rel="noopener noreferrer" href="https://yapi.ymfe.org/case.html" >
<Tooltip title="点击查看文档"><Icon type="question-circle-o" /></Tooltip>
</a></h2>
<Button type="primary" style={{ float: 'right' }} onClick={this.executeTests}>开始测试</Button>
<Table.Provider
components={components}

View File

@ -30,7 +30,6 @@ var langTools = ace.acequire("ace/ext/language_tools"),
{ name: '颜色rgb', mock: '@rgb' },
{ name: '颜色hsl', mock: '@hsl' },
{ name: '整数', mock: '@integer' },
{ name: '浮点数', mock: '@float' },
{ name: 'email', mock: '@email' },
{ name: '大段文本', mock: '@paragraph' },
{ name: '句子', mock: '@sentence' },