| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033 |
- import React, { PureComponent as Component } from 'react';
- import PropTypes from 'prop-types';
- import {
- Button,
- Input,
- Checkbox,
- Modal,
- Select,
- Spin,
- Icon,
- Collapse,
- Tooltip,
- Tabs,
- Switch,
- Row,
- Col,
- Alert
- } from 'antd';
- import constants from '../../constants/variable.js';
- import AceEditor from 'client/components/AceEditor/AceEditor';
- import _ from 'underscore';
- import { isJson, deepCopyJson, json5_parse } from '../../common.js';
- import axios from 'axios';
- import ModalPostman from '../ModalPostman/index.js';
- import CheckCrossInstall, { initCrossRequest } from './CheckCrossInstall.js';
- import './Postman.scss';
- import ProjectEnv from '../../containers/Project/Setting/ProjectEnv/index.js';
- import json5 from 'json5';
- const { handleParamsValue, ArrayToObject, schemaValidator } = require('common/utils.js');
- const {
- handleParams,
- checkRequestBodyIsRaw,
- handleContentType,
- crossRequest,
- checkNameIsExistInArray
- } = require('common/postmanLib.js');
- const createContext = require('common/createContext')
- const HTTP_METHOD = constants.HTTP_METHOD;
- const InputGroup = Input.Group;
- const Option = Select.Option;
- const Panel = Collapse.Panel;
- export const InsertCodeMap = [
- {
- code: 'assert.equal(status, 200)',
- title: '断言 httpCode 等于 200'
- },
- {
- code: 'assert.equal(body.code, 0)',
- title: '断言返回数据 code 是 0'
- },
- {
- code: 'assert.notEqual(status, 404)',
- title: '断言 httpCode 不是 404'
- },
- {
- code: 'assert.notEqual(body.code, 40000)',
- title: '断言返回数据 code 不是 40000'
- },
- {
- code: 'assert.deepEqual(body, {"code": 0})',
- title: '断言对象 body 等于 {"code": 0}'
- },
- {
- code: 'assert.notDeepEqual(body, {"code": 0})',
- title: '断言对象 body 不等于 {"code": 0}'
- }
- ];
- const ParamsNameComponent = props => {
- const { example, desc, name } = props;
- const isNull = !example && !desc;
- const TooltipTitle = () => {
- return (
- <div>
- {example && (
- <div>
- 示例: <span className="table-desc">{example}</span>
- </div>
- )}
- {desc && (
- <div>
- 备注: <span className="table-desc">{desc}</span>
- </div>
- )}
- </div>
- );
- };
- return (
- <div>
- {isNull ? (
- <Input disabled value={name} className="key" />
- ) : (
- <Tooltip placement="topLeft" title={<TooltipTitle />}>
- <Input disabled value={name} className="key" />
- </Tooltip>
- )}
- </div>
- );
- };
- ParamsNameComponent.propTypes = {
- example: PropTypes.string,
- desc: PropTypes.string,
- name: PropTypes.string
- };
- export default class Run extends Component {
- static propTypes = {
- data: PropTypes.object, //接口原有数据
- save: PropTypes.func, //保存回调方法
- type: PropTypes.string, //enum[case, inter], 判断是在接口页面使用还是在测试集
- curUid: PropTypes.number.isRequired,
- interfaceId: PropTypes.number.isRequired,
- projectId: PropTypes.number.isRequired
- };
- constructor(props) {
- super(props);
- this.state = {
- loading: false,
- resStatusCode: null,
- test_valid_msg: null,
- resStatusText: null,
- case_env: '',
- mock_verify: false,
- enable_script: false,
- test_script: '',
- hasPlugin: true,
- inputValue: '',
- cursurPosition: { row: 1, column: -1 },
- envModalVisible: false,
- test_res_header: null,
- test_res_body: null,
- autoPreviewHTML: true,
- ...this.props.data
- };
- }
- get testResponseBodyIsHTML() {
- const hd = this.state.test_res_header
- return hd != null
- && typeof hd === 'object'
- && String(hd['Content-Type'] || hd['content-type']).indexOf('text/html') !== -1
- }
- checkInterfaceData(data) {
- if (!data || typeof data !== 'object' || !data._id) {
- return false;
- }
- return true;
- }
- // 整合header信息
- handleReqHeader = (value, env) => {
- let index = value
- ? env.findIndex(item => {
- return item.name === value;
- })
- : 0;
- index = index === -1 ? 0 : index;
- let req_header = [].concat(this.props.data.req_headers || []);
- let header = [].concat(env[index].header || []);
- header.forEach(item => {
- if (!checkNameIsExistInArray(item.name, req_header)) {
- item = {
- ...item,
- abled: true
- };
- req_header.push(item);
- }
- });
- req_header = req_header.filter(item => {
- return item && typeof item === 'object';
- });
- return req_header;
- };
- selectDomain = value => {
- let headers = this.handleReqHeader(value, this.state.env);
- this.setState({
- case_env: value,
- req_headers: headers
- });
- };
- async initState(data) {
- if (!this.checkInterfaceData(data)) {
- return null;
- }
- const { req_body_other, req_body_type, req_body_is_json_schema } = data;
- let body = req_body_other;
- // 运行时才会进行转换
- if (
- this.props.type === 'inter' &&
- req_body_type === 'json' &&
- req_body_other &&
- req_body_is_json_schema
- ) {
- let schema = {};
- try {
- schema = json5.parse(req_body_other);
- } catch (e) {
- console.log('e', e);
- return;
- }
- let result = await axios.post('/api/interface/schema2json', {
- schema: schema,
- required: true
- });
- body = JSON.stringify(result.data);
- }
- let example = {}
- if(this.props.type === 'inter'){
- example = ['req_headers', 'req_query', 'req_body_form'].reduce(
- (res, key) => {
- res[key] = (data[key] || []).map(item => {
- if (
- item.type !== 'file' // 不是文件类型
- && (item.value == null || item.value === '') // 初始值为空
- && item.example != null // 有示例值
- ) {
- item.value = item.example;
- }
- return item;
- })
- return res;
- },
- {}
- )
- }
- this.setState(
- {
- ...this.state,
- test_res_header: null,
- test_res_body: null,
- ...data,
- ...example,
- req_body_other: body,
- resStatusCode: null,
- test_valid_msg: null,
- resStatusText: null
- },
- () => this.props.type === 'inter' && this.initEnvState(data.case_env, data.env)
- );
- }
- initEnvState(case_env, env) {
- let headers = this.handleReqHeader(case_env, env);
- this.setState(
- {
- req_headers: headers,
- env: env
- },
- () => {
- let s = !_.find(env, item => item.name === this.state.case_env);
- if (!this.state.case_env || s) {
- this.setState({
- case_env: this.state.env[0].name
- });
- }
- }
- );
- }
- componentWillMount() {
- this._crossRequestInterval = initCrossRequest(hasPlugin => {
- this.setState({
- hasPlugin: hasPlugin
- });
- });
- this.initState(this.props.data);
- }
- componentWillUnmount() {
- clearInterval(this._crossRequestInterval);
- }
- componentWillReceiveProps(nextProps) {
- if (this.checkInterfaceData(nextProps.data) && this.checkInterfaceData(this.props.data)) {
- if (nextProps.data._id !== this.props.data._id) {
- this.initState(nextProps.data);
- } else if (nextProps.data.interface_up_time !== this.props.data.interface_up_time) {
- this.initState(nextProps.data);
- }
- if (nextProps.data.env !== this.props.data.env) {
- this.initEnvState(this.state.case_env, nextProps.data.env);
- }
- }
- }
- handleValue(val, global) {
- let globalValue = ArrayToObject(global);
- return handleParamsValue(val, {
- global: globalValue
- });
- }
- onOpenTest = d => {
- this.setState({
- test_script: d.text
- });
- };
- handleInsertCode = code => {
- this.aceEditor.editor.insertCode(code);
- };
- handleRequestBody = d => {
- this.setState({
- req_body_other: d.text
- });
- };
- reqRealInterface = async () => {
- if (this.state.loading === true) {
- this.setState({
- loading: false
- });
- return null;
- }
- this.setState({
- loading: true
- });
- let options = handleParams(this.state, this.handleValue),
- result;
- try {
- options.taskId = this.props.curUid;
- result = await crossRequest(options, this.state.pre_script, this.state.after_script, createContext(
- this.props.curUid,
- this.props.projectId,
- this.props.interfaceId
- ));
- result = {
- header: result.res.header,
- body: result.res.body,
- status: result.res.status,
- statusText: result.res.statusText,
- runTime: result.runTime
- };
- } catch (data) {
- result = {
- header: data.header,
- body: data.body,
- status: null,
- statusText: data.message
- };
- }
- if (this.state.loading === true) {
- this.setState({
- loading: false
- });
- } else {
- return null;
- }
- let tempJson = result.body;
- if (tempJson && typeof tempJson === 'object') {
- result.body = JSON.stringify(tempJson, null, ' ');
- this.setState({
- res_body_type: 'json'
- });
- } else if (isJson(result.body)) {
- this.setState({
- res_body_type: 'json'
- });
- }
- // 对 返回值数据结构 和定义的 返回数据结构 进行 格式校验
- let validResult = this.resBodyValidator(this.props.data, result.body);
- if (!validResult.valid) {
- this.setState({ test_valid_msg: `返回参数 ${validResult.message}` });
- } else {
- this.setState({ test_valid_msg: '' });
- }
- this.setState({
- resStatusCode: result.status,
- resStatusText: result.statusText,
- test_res_header: result.header,
- test_res_body: result.body
- });
- };
- // 返回数据与定义数据的比较判断
- resBodyValidator = (interfaceData, test_res_body) => {
- const { res_body_type, res_body_is_json_schema, res_body } = interfaceData;
- let validResult = { valid: true };
- if (res_body_type === 'json' && res_body_is_json_schema) {
- const schema = json5_parse(res_body);
- const params = json5_parse(test_res_body);
- validResult = schemaValidator(schema, params);
- }
- return validResult;
- };
- changeParam = (name, v, index, key) => {
-
- key = key || 'value';
- const pathParam = deepCopyJson(this.state[name]);
- pathParam[index][key] = v;
- if (key === 'value') {
- pathParam[index].enable = !!v;
- }
- this.setState({
- [name]: pathParam
- });
- };
- changeBody = (v, index, key) => {
- const bodyForm = deepCopyJson(this.state.req_body_form);
- key = key || 'value';
- if (key === 'value') {
- bodyForm[index].enable = !!v;
- if (bodyForm[index].type === 'file') {
- bodyForm[index].value = 'file_' + index;
- } else {
- bodyForm[index].value = v;
- }
- } else if (key === 'enable') {
- bodyForm[index].enable = v;
- }
- this.setState({ req_body_form: bodyForm });
- };
- // 模态框的相关操作
- showModal = (val, index, type) => {
- let inputValue = '';
- let cursurPosition;
- if (type === 'req_body_other') {
- // req_body
- let editor = this.aceEditor.editor.editor;
- cursurPosition = editor.session.doc.positionToIndex(editor.selection.getCursor());
- // 获取选中的数据
- inputValue = this.getInstallValue(val || '', cursurPosition).val;
- } else {
- // 其他input 输入
- let oTxt1 = document.getElementById(`${type}_${index}`);
- cursurPosition = oTxt1.selectionStart;
- inputValue = this.getInstallValue(val || '', cursurPosition).val;
- // cursurPosition = {row: 1, column: position}
- }
- this.setState({
- modalVisible: true,
- inputIndex: index,
- inputValue,
- cursurPosition,
- modalType: type
- });
- };
- // 点击插入
- handleModalOk = val => {
- const { inputIndex, modalType } = this.state;
- if (modalType === 'req_body_other') {
- this.changeInstallBody(modalType, val);
- } else {
- this.changeInstallParam(modalType, val, inputIndex);
- }
- this.setState({ modalVisible: false });
- };
- // 根据鼠标位置往req_body中动态插入数据
- changeInstallBody = (type, value) => {
- const pathParam = deepCopyJson(this.state[type]);
- // console.log(pathParam)
- let oldValue = pathParam || '';
- let newValue = this.getInstallValue(oldValue, this.state.cursurPosition);
- let left = newValue.left;
- let right = newValue.right;
- this.setState({
- [type]: `${left}${value}${right}`
- });
- };
- // 获取截取的字符串
- getInstallValue = (oldValue, cursurPosition) => {
- let left = oldValue.substr(0, cursurPosition);
- let right = oldValue.substr(cursurPosition);
- let leftPostion = left.lastIndexOf('{{');
- let leftPostion2 = left.lastIndexOf('}}');
- let rightPostion = right.indexOf('}}');
- // console.log(leftPostion, leftPostion2,rightPostion, rightPostion2);
- let val = '';
- // 需要切除原来的变量
- if (leftPostion !== -1 && rightPostion !== -1 && leftPostion > leftPostion2) {
- left = left.substr(0, leftPostion);
- right = right.substr(rightPostion + 2);
- val = oldValue.substring(leftPostion, cursurPosition + rightPostion + 2);
- }
- return {
- left,
- right,
- val
- };
- };
- // 根据鼠标位置动态插入数据
- changeInstallParam = (name, v, index, key) => {
- key = key || 'value';
- const pathParam = deepCopyJson(this.state[name]);
- let oldValue = pathParam[index][key] || '';
- let newValue = this.getInstallValue(oldValue, this.state.cursurPosition);
- let left = newValue.left;
- let right = newValue.right;
- pathParam[index][key] = `${left}${v}${right}`;
- this.setState({
- [name]: pathParam
- });
- };
- // 取消参数插入
- handleModalCancel = () => {
- this.setState({ modalVisible: false, cursurPosition: -1 });
- };
- // 环境变量模态框相关操作
- showEnvModal = () => {
- this.setState({
- envModalVisible: true
- });
- };
- handleEnvOk = (newEnv, index) => {
- this.setState({
- envModalVisible: false,
- case_env: newEnv[index].name
- });
- };
- handleEnvCancel = () => {
- this.setState({
- envModalVisible: false
- });
- };
- render() {
- const {
- method,
- env,
- path,
- req_params = [],
- req_headers = [],
- req_query = [],
- req_body_type,
- req_body_form = [],
- loading,
- case_env,
- inputValue,
- hasPlugin
- } = this.state;
- // console.log(env);
- return (
- <div className="interface-test postman">
- {this.state.modalVisible && (
- <ModalPostman
- visible={this.state.modalVisible}
- handleCancel={this.handleModalCancel}
- handleOk={this.handleModalOk}
- inputValue={inputValue}
- envType={this.props.type}
- id={+this.state._id}
- />
- )}
- {this.state.envModalVisible && (
- <Modal
- title="环境设置"
- visible={this.state.envModalVisible}
- onOk={this.handleEnvOk}
- onCancel={this.handleEnvCancel}
- footer={null}
- width={800}
- className="env-modal"
- >
- <ProjectEnv projectId={this.props.data.project_id} onOk={this.handleEnvOk} />
- </Modal>
- )}
- <CheckCrossInstall hasPlugin={hasPlugin} />
- <div className="url">
- <InputGroup compact style={{ display: 'flex' }}>
- <Select disabled value={method} style={{ flexBasis: 60 }}>
- {Object.keys(HTTP_METHOD).map(name => {
- <Option value={name.toUpperCase()}>{name.toUpperCase()}</Option>;
- })}
- </Select>
- <Select
- value={case_env}
- style={{ flexBasis: 180, flexGrow: 1 }}
- onSelect={this.selectDomain}
- >
- {env.map((item, index) => (
- <Option value={item.name} key={index}>
- {item.name + ':' + item.domain}
- </Option>
- ))}
- <Option value="环境配置" disabled style={{ cursor: 'pointer', color: '#2395f1' }}>
- <Button type="primary" onClick={this.showEnvModal}>
- 环境配置
- </Button>
- </Option>
- </Select>
- <Input
- disabled
- value={path}
- onChange={this.changePath}
- spellCheck="false"
- style={{ flexBasis: 180, flexGrow: 1 }}
- />
- </InputGroup>
- <Tooltip
- placement="bottom"
- title={(() => {
- if (hasPlugin) {
- return '发送请求';
- } else {
- return '请安装 cross-request 插件';
- }
- })()}
- >
- <Button
- disabled={!hasPlugin}
- onClick={this.reqRealInterface}
- type="primary"
- style={{ marginLeft: 10 }}
- icon={loading ? 'loading' : ''}
- >
- {loading ? '取消' : '发送'}
- </Button>
- </Tooltip>
- <Tooltip
- placement="bottom"
- title={() => {
- return this.props.type === 'inter' ? '保存到测试集' : '更新该用例';
- }}
- >
- <Button onClick={this.props.save} type="primary" style={{ marginLeft: 10 }}>
- {this.props.type === 'inter' ? '保存' : '更新'}
- </Button>
- </Tooltip>
- </div>
- <Collapse defaultActiveKey={['0', '1', '2', '3']} bordered={true}>
- <Panel
- header="PATH PARAMETERS"
- key="0"
- className={req_params.length === 0 ? 'hidden' : ''}
- >
- {req_params.map((item, index) => {
- return (
- <div key={index} className="key-value-wrap">
- {/* <Tooltip
- placement="topLeft"
- title={<TooltipContent example={item.example} desc={item.desc} />}
- >
- <Input disabled value={item.name} className="key" />
- </Tooltip> */}
- <ParamsNameComponent example={item.example} desc={item.desc} name={item.name} />
- <span className="eq-symbol">=</span>
- <Input
- value={item.value}
- className="value"
- onChange={e => this.changeParam('req_params', e.target.value, index)}
- placeholder="参数值"
- id={`req_params_${index}`}
- addonAfter={
- <Icon
- type="edit"
- onClick={() => this.showModal(item.value, index, 'req_params')}
- />
- }
- />
- </div>
- );
- })}
- <Button
- style={{ display: 'none' }}
- type="primary"
- icon="plus"
- onClick={this.addPathParam}
- >
- 添加Path参数
- </Button>
- </Panel>
- <Panel
- header="QUERY PARAMETERS"
- key="1"
- className={req_query.length === 0 ? 'hidden' : ''}
- >
- {req_query.map((item, index) => {
- return (
- <div key={index} className="key-value-wrap">
- {/* <Tooltip
- placement="topLeft"
- title={<TooltipContent example={item.example} desc={item.desc} />}
- >
- <Input disabled value={item.name} className="key" />
- </Tooltip> */}
- <ParamsNameComponent example={item.example} desc={item.desc} name={item.name} />
-
- {item.required == 1 ? (
- <Checkbox className="params-enable" checked={true} disabled />
- ) : (
- <Checkbox
- className="params-enable"
- checked={item.enable}
- onChange={e =>
- this.changeParam('req_query', e.target.checked, index, 'enable')
- }
- />
- )}
- <span className="eq-symbol">=</span>
- <Input
- value={item.value}
- className="value"
- onChange={e => this.changeParam('req_query', e.target.value, index)}
- placeholder="参数值"
- id={`req_query_${index}`}
- addonAfter={
- <Icon
- type="edit"
- onClick={() => this.showModal(item.value, index, 'req_query')}
- />
- }
- />
- </div>
- );
- })}
- <Button style={{ display: 'none' }} type="primary" icon="plus" onClick={this.addQuery}>
- 添加Query参数
- </Button>
- </Panel>
- <Panel header="HEADERS" key="2" className={req_headers.length === 0 ? 'hidden' : ''}>
- {req_headers.map((item, index) => {
- return (
- <div key={index} className="key-value-wrap">
- {/* <Tooltip
- placement="topLeft"
- title={<TooltipContent example={item.example} desc={item.desc} />}
- >
- <Input disabled value={item.name} className="key" />
- </Tooltip> */}
- <ParamsNameComponent example={item.example} desc={item.desc} name={item.name} />
- <span className="eq-symbol">=</span>
- <Input
- value={item.value}
- disabled={!!item.abled}
- className="value"
- onChange={e => this.changeParam('req_headers', e.target.value, index)}
- placeholder="参数值"
- id={`req_headers_${index}`}
- addonAfter={
- !item.abled && (
- <Icon
- type="edit"
- onClick={() => this.showModal(item.value, index, 'req_headers')}
- />
- )
- }
- />
- </div>
- );
- })}
- <Button style={{ display: 'none' }} type="primary" icon="plus" onClick={this.addHeader}>
- 添加Header
- </Button>
- </Panel>
- <Panel
- header={
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
- <Tooltip title="F9 全屏编辑">BODY(F9)</Tooltip>
- </div>
- }
- key="3"
- className={
- HTTP_METHOD[method].request_body &&
- ((req_body_type === 'form' && req_body_form.length > 0) || req_body_type !== 'form')
- ? 'POST'
- : 'hidden'
- }
- >
- <div
- style={{ display: checkRequestBodyIsRaw(method, req_body_type) ? 'block' : 'none' }}
- >
- {req_body_type === 'json' && (
- <div className="adv-button">
- <Button
- onClick={() => this.showModal(this.state.req_body_other, 0, 'req_body_other')}
- >
- 高级参数设置
- </Button>
- <Tooltip title="高级参数设置只在json字段值中生效">
- {' '}
- <Icon type="question-circle-o" />
- </Tooltip>
- </div>
- )}
- <AceEditor
- className="pretty-editor"
- ref={editor => (this.aceEditor = editor)}
- data={this.state.req_body_other}
- mode={req_body_type === 'json' ? null : 'text'}
- onChange={this.handleRequestBody}
- fullScreen={true}
- />
- </div>
- {HTTP_METHOD[method].request_body &&
- req_body_type === 'form' && (
- <div>
- {req_body_form.map((item, index) => {
- return (
- <div key={index} className="key-value-wrap">
- {/* <Tooltip
- placement="topLeft"
- title={<TooltipContent example={item.example} desc={item.desc} />}
- >
- <Input disabled value={item.name} className="key" />
- </Tooltip> */}
- <ParamsNameComponent
- example={item.example}
- desc={item.desc}
- name={item.name}
- />
-
- {item.required == 1 ? (
- <Checkbox className="params-enable" checked={true} disabled />
- ) : (
- <Checkbox
- className="params-enable"
- checked={item.enable}
- onChange={e => this.changeBody(e.target.checked, index, 'enable')}
- />
- )}
- <span className="eq-symbol">=</span>
- {item.type === 'file' ? (
- '因Chrome最新版安全策略限制,不再支持文件上传'
- // <Input
- // type="file"
- // id={'file_' + index}
- // onChange={e => this.changeBody(e.target.value, index, 'value')}
- // multiple
- // className="value"
- // />
- ) : (
- <Input
- value={item.value}
- className="value"
- onChange={e => this.changeBody(e.target.value, index)}
- placeholder="参数值"
- id={`req_body_form_${index}`}
- addonAfter={
- <Icon
- type="edit"
- onClick={() => this.showModal(item.value, index, 'req_body_form')}
- />
- }
- />
- )}
- </div>
- );
- })}
- <Button
- style={{ display: 'none' }}
- type="primary"
- icon="plus"
- onClick={this.addBody}
- >
- 添加Form参数
- </Button>
- </div>
- )}
- {HTTP_METHOD[method].request_body &&
- req_body_type === 'file' && (
- <div>
- <Input type="file" id="single-file" />
- </div>
- )}
- </Panel>
- </Collapse>
- <Tabs size="large" defaultActiveKey="res" className="response-tab">
- <Tabs.TabPane tab="Response" key="res">
- <Spin spinning={this.state.loading}>
- <h2
- style={{ display: this.state.resStatusCode ? '' : 'none' }}
- className={
- 'res-code ' +
- (this.state.resStatusCode >= 200 &&
- this.state.resStatusCode < 400 &&
- !this.state.loading
- ? 'success'
- : 'fail')
- }
- >
- {this.state.resStatusCode + ' ' + this.state.resStatusText}
- </h2>
- <div>
- <a rel="noopener noreferrer" target="_blank" href="https://juejin.im/post/5c888a3e5188257dee0322af">YApi 新版如何查看 http 请求数据</a>
- </div>
- {this.state.test_valid_msg && (
- <Alert
- message={
- <span>
- Warning
- <Tooltip title="针对定义为 json schema 的返回数据进行格式校验">
- <Icon type="question-circle-o" />
- </Tooltip>
- </span>
- }
- type="warning"
- showIcon
- description={this.state.test_valid_msg}
- />
- )}
- <div className="container-header-body">
- <div className="header">
- <div className="container-title">
- <h4>Headers</h4>
- </div>
- <AceEditor
- callback={editor => {
- editor.renderer.setShowGutter(false);
- }}
- readOnly={true}
- className="pretty-editor-header"
- data={this.state.test_res_header}
- mode="json"
- />
- </div>
- <div className="resizer">
- <div className="container-title">
- <h4 style={{ visibility: 'hidden' }}>1</h4>
- </div>
- </div>
- <div className="body">
- <div className="container-title">
- <h4>Body</h4>
- <Checkbox
- checked={this.state.autoPreviewHTML}
- onChange={e => this.setState({ autoPreviewHTML: e.target.checked })}>
- <span>自动预览HTML</span>
- </Checkbox>
- </div>
- {
- this.state.autoPreviewHTML && this.testResponseBodyIsHTML
- ? <iframe
- className="pretty-editor-body"
- srcDoc={this.state.test_res_body}
- />
- : <AceEditor
- readOnly={true}
- className="pretty-editor-body"
- data={this.state.test_res_body}
- mode={handleContentType(this.state.test_res_header)}
- />
- }
- </div>
- </div>
- </Spin>
- </Tabs.TabPane>
- {this.props.type === 'case' ? (
- <Tabs.TabPane
- className="response-test"
- tab={<Tooltip title="测试脚本,可断言返回结果,使用方法请查看文档">Test</Tooltip>}
- key="test"
- >
- <h3 style={{ margin: '5px' }}>
- 是否开启:
- <Switch
- checked={this.state.enable_script}
- onChange={e => this.setState({ enable_script: e })}
- />
- </h3>
- <p style={{ margin: '10px' }}>注:Test 脚本只有做自动化测试才执行</p>
- <Row>
- <Col span="18">
- <AceEditor
- onChange={this.onOpenTest}
- className="case-script"
- data={this.state.test_script}
- ref={aceEditor => {
- this.aceEditor = aceEditor;
- }}
- />
- </Col>
- <Col span="6">
- <div className="insert-code">
- {InsertCodeMap.map(item => {
- return (
- <div
- style={{ cursor: 'pointer' }}
- className="code-item"
- key={item.title}
- onClick={() => {
- this.handleInsertCode('\n' + item.code);
- }}
- >
- {item.title}
- </div>
- );
- })}
- </div>
- </Col>
- </Row>
- </Tabs.TabPane>
- ) : null}
- </Tabs>
- </div>
- );
- }
- }
|