| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243 |
- import React, { PureComponent as Component } from 'react';
- import { connect } from 'react-redux';
- import PropTypes from 'prop-types';
- import { withRouter } from 'react-router';
- import { Link } from 'react-router-dom';
- //import constants from '../../../../constants/variable.js'
- import { Tooltip, Icon,Input, Button, Row, Col, Spin, Modal, message, Select, Switch } from 'antd';
- import {
- fetchInterfaceColList,
- fetchCaseList,
- setColData,
- fetchCaseEnvList
- } from '../../../../reducer/modules/interfaceCol';
- import HTML5Backend from 'react-dnd-html5-backend';
- import { getToken, getEnv } from '../../../../reducer/modules/project';
- import { DragDropContext } from 'react-dnd';
- import AceEditor from 'client/components/AceEditor/AceEditor';
- import * as Table from 'reactabular-table';
- import * as dnd from 'reactabular-dnd';
- import * as resolve from 'table-resolver';
- import axios from 'axios';
- import CaseReport from './CaseReport.js';
- import _ from 'underscore';
- import { initCrossRequest } from 'client/components/Postman/CheckCrossInstall.js';
- import produce from 'immer';
- import {InsertCodeMap} from 'client/components/Postman/Postman.js'
- const {
- handleParams,
- crossRequest,
- handleCurrDomain,
- checkNameIsExistInArray
- } = require('common/postmanLib.js');
- const { handleParamsValue, json_parse, ArrayToObject } = require('common/utils.js');
- import CaseEnv from 'client/components/CaseEnv';
- import Label from '../../../../components/Label/Label.js';
- const Option = Select.Option;
- const createContext = require('common/createContext')
- import copy from 'copy-to-clipboard';
- const defaultModalStyle = {
- top: 10
- }
- function handleReport(json) {
- try {
- return JSON.parse(json);
- } catch (e) {
- return {};
- }
- }
- @connect(
- state => {
- return {
- interfaceColList: state.interfaceCol.interfaceColList,
- currColId: state.interfaceCol.currColId,
- currCaseId: state.interfaceCol.currCaseId,
- isShowCol: state.interfaceCol.isShowCol,
- isRander: state.interfaceCol.isRander,
- currCaseList: state.interfaceCol.currCaseList,
- currProject: state.project.currProject,
- token: state.project.token,
- envList: state.interfaceCol.envList,
- curProjectRole: state.project.currProject.role,
- projectEnv: state.project.projectEnv,
- curUid: state.user.uid
- };
- },
- {
- fetchInterfaceColList,
- fetchCaseList,
- setColData,
- getToken,
- getEnv,
- fetchCaseEnvList
- }
- )
- @withRouter
- @DragDropContext(HTML5Backend)
- class InterfaceColContent extends Component {
- static propTypes = {
- match: PropTypes.object,
- interfaceColList: PropTypes.array,
- fetchInterfaceColList: PropTypes.func,
- fetchCaseList: PropTypes.func,
- setColData: PropTypes.func,
- history: PropTypes.object,
- currCaseList: PropTypes.array,
- currColId: PropTypes.number,
- currCaseId: PropTypes.number,
- isShowCol: PropTypes.bool,
- isRander: PropTypes.bool,
- currProject: PropTypes.object,
- getToken: PropTypes.func,
- token: PropTypes.string,
- curProjectRole: PropTypes.string,
- getEnv: PropTypes.func,
- projectEnv: PropTypes.object,
- fetchCaseEnvList: PropTypes.func,
- envList: PropTypes.array,
- curUid: PropTypes.number
- };
- constructor(props) {
- super(props);
- this.reports = {};
- this.records = {};
- this.state = {
- rows: [],
- reports: {},
- visible: false,
- curCaseid: null,
- hasPlugin: false,
- advVisible: false,
- curScript: '',
- enableScript: false,
- autoVisible: false,
- mode: 'html',
- email: false,
- download: false,
- currColEnvObj: {},
- collapseKey: '1',
- commonSettingModalVisible: false,
- commonSetting: {
- checkHttpCodeIs200: false,
- checkResponseField: {
- name: 'code',
- value: '0',
- enable: false
- },
- checkResponseSchema: false,
- checkScript:{
- enable: false,
- content: ''
- }
- }
- };
- this.onRow = this.onRow.bind(this);
- this.onMoveRow = this.onMoveRow.bind(this);
- }
- async handleColIdChange(newColId){
- this.props.setColData({
- currColId: +newColId,
- isShowCol: true,
- isRander: false
- });
- let result = await this.props.fetchCaseList(newColId);
- if (result.payload.data.errcode === 0) {
- this.reports = handleReport(result.payload.data.colData.test_report);
- this.setState({
- commonSetting:{
- ...this.state.commonSetting,
- ...result.payload.data.colData
- }
- })
- }
- await this.props.fetchCaseList(newColId);
- await this.props.fetchCaseEnvList(newColId);
- this.changeCollapseClose();
- this.handleColdata(this.props.currCaseList);
- }
- async componentWillMount() {
- const result = await this.props.fetchInterfaceColList(this.props.match.params.id);
- await this.props.getToken(this.props.match.params.id);
- let { currColId } = this.props;
- const params = this.props.match.params;
- const { actionId } = params;
- this.currColId = currColId = +actionId || result.payload.data.data[0]._id;
- this.props.history.push('/project/' + params.id + '/interface/col/' + currColId);
- if (currColId && currColId != 0) {
- await this.handleColIdChange(currColId)
- }
- this._crossRequestInterval = initCrossRequest(hasPlugin => {
- this.setState({ hasPlugin: hasPlugin });
- });
- }
- componentWillUnmount() {
- clearInterval(this._crossRequestInterval);
- }
- // 更新分类简介
- handleChangeInterfaceCol = (desc, name) => {
- let params = {
- col_id: this.props.currColId,
- name: name,
- desc: desc
- };
- axios.post('/api/col/up_col', params).then(async res => {
- if (res.data.errcode) {
- return message.error(res.data.errmsg);
- }
- let project_id = this.props.match.params.id;
- await this.props.fetchInterfaceColList(project_id);
- message.success('接口集合简介更新成功');
- });
- };
- // 整合header信息
- handleReqHeader = (project_id, req_header, case_env) => {
- let envItem = _.find(this.props.envList, item => {
- return item._id === project_id;
- });
- let currDomain = handleCurrDomain(envItem && envItem.env, case_env);
- let header = currDomain.header;
- header.forEach(item => {
- if (!checkNameIsExistInArray(item.name, req_header)) {
- // item.abled = true;
- item = {
- ...item,
- abled: true
- };
- req_header.push(item);
- }
- });
- return req_header;
- };
- handleColdata = (rows, currColEnvObj = {}) => {
- let that = this;
- let newRows = produce(rows, draftRows => {
- draftRows.map(item => {
- item.id = item._id;
- item._test_status = item.test_status;
- if(currColEnvObj[item.project_id]){
- item.case_env =currColEnvObj[item.project_id];
- }
- item.req_headers = that.handleReqHeader(item.project_id, item.req_headers, item.case_env);
- return item;
- });
- });
- this.setState({ rows: newRows });
- };
- executeTests = async () => {
- for (let i = 0, l = this.state.rows.length, newRows, curitem; i < l; i++) {
- let { rows } = this.state;
- let envItem = _.find(this.props.envList, item => {
- return item._id === rows[i].project_id;
- });
- curitem = Object.assign(
- {},
- rows[i],
- {
- env: envItem.env,
- pre_script: this.props.currProject.pre_script,
- after_script: this.props.currProject.after_script
- },
- { test_status: 'loading' }
- );
- newRows = [].concat([], rows);
- newRows[i] = curitem;
- this.setState({ rows: newRows });
- let status = 'error',
- result;
- try {
- result = await this.handleTest(curitem);
- if (result.code === 400) {
- status = 'error';
- } else if (result.code === 0) {
- status = 'ok';
- } else if (result.code === 1) {
- status = 'invalid';
- }
- } catch (e) {
- console.error(e);
- status = 'error';
- result = e;
- }
- //result.body = result.data;
- this.reports[curitem._id] = result;
- this.records[curitem._id] = {
- status: result.status,
- params: result.params,
- body: result.res_body
- };
- curitem = Object.assign({}, rows[i], { test_status: status });
- newRows = [].concat([], rows);
- newRows[i] = curitem;
- this.setState({ rows: newRows });
- }
- await axios.post('/api/col/up_col', {
- col_id: this.props.currColId,
- test_report: JSON.stringify(this.reports)
- });
- };
- handleTest = async interfaceData => {
- let requestParams = {};
- let options = handleParams(interfaceData, this.handleValue, requestParams);
- let result = {
- code: 400,
- msg: '数据异常',
- validRes: []
- };
- try {
- let data = await crossRequest(options, interfaceData.pre_script, interfaceData.after_script, createContext(
- this.props.curUid,
- this.props.match.params.id,
- interfaceData.interface_id
- ));
- options.taskId = this.props.curUid;
- let res = (data.res.body = json_parse(data.res.body));
- result = {
- ...options,
- ...result,
- res_header: data.res.header,
- res_body: res,
- status: data.res.status,
- statusText: data.res.statusText
- };
- if (options.data && typeof options.data === 'object') {
- requestParams = {
- ...requestParams,
- ...options.data
- };
- }
- let validRes = [];
- let responseData = Object.assign(
- {},
- {
- status: data.res.status,
- body: res,
- header: data.res.header,
- statusText: data.res.statusText
- }
- );
- // 断言测试
- await this.handleScriptTest(interfaceData, responseData, validRes, requestParams);
- if (validRes.length === 0) {
- result.code = 0;
- result.validRes = [
- {
- message: '验证通过'
- }
- ];
- } else if (validRes.length > 0) {
- result.code = 1;
- result.validRes = validRes;
- }
- } catch (data) {
- result = {
- ...options,
- ...result,
- res_header: data.header,
- res_body: data.body || data.message,
- status: 0,
- statusText: data.message,
- code: 400,
- validRes: [
- {
- message: data.message
- }
- ]
- };
- }
- result.params = requestParams;
- return result;
- };
- //response, validRes
- // 断言测试
- handleScriptTest = async (interfaceData, response, validRes, requestParams) => {
- // 是否启动断言
- try {
- let test = await axios.post('/api/col/run_script', {
- response: response,
- records: this.records,
- script: interfaceData.test_script,
- params: requestParams,
- col_id: this.props.currColId,
- interface_id: interfaceData.interface_id
- });
- if (test.data.errcode !== 0) {
- test.data.data.logs.forEach(item => {
- validRes.push({ message: item });
- });
- }
- } catch (err) {
- validRes.push({
- message: 'Error: ' + err.message
- });
- }
- };
- handleValue = (val, global) => {
- let globalValue = ArrayToObject(global);
- let context = Object.assign({}, { global: globalValue }, this.records);
- return handleParamsValue(val, context);
- };
- arrToObj = (arr, requestParams) => {
- arr = arr || [];
- const obj = {};
- arr.forEach(item => {
- if (item.name && item.enable && item.type !== 'file') {
- obj[item.name] = this.handleValue(item.value);
- if (requestParams) {
- requestParams[item.name] = obj[item.name];
- }
- }
- });
- return obj;
- };
- onRow(row) {
- return { rowId: row.id, onMove: this.onMoveRow, onDrop: this.onDrop };
- }
- onDrop = () => {
- let changes = [];
- this.state.rows.forEach((item, index) => {
- changes.push({ id: item._id, index: index });
- });
- axios.post('/api/col/up_case_index', changes).then(() => {
- this.props.fetchInterfaceColList(this.props.match.params.id);
- });
- };
- onMoveRow({ sourceRowId, targetRowId }) {
- let rows = dnd.moveRows({ sourceRowId, targetRowId })(this.state.rows);
- if (rows) {
- this.setState({ rows });
- }
- }
- onChangeTest = d => {
-
- this.setState({
- commonSetting: {
- ...this.state.commonSetting,
- checkScript: {
- ...this.state.commonSetting.checkScript,
- content: d.text
- }
- }
- });
- };
- handleInsertCode = code => {
- this.aceEditor.editor.insertCode(code);
- };
- async componentWillReceiveProps(nextProps) {
- let newColId = !isNaN(nextProps.match.params.actionId) ? +nextProps.match.params.actionId : 0;
- if ((newColId && this.currColId && newColId !== this.currColId) || nextProps.isRander) {
- this.currColId = newColId;
- this.handleColIdChange(newColId)
- }
- }
- // 测试用例环境面板折叠
- changeCollapseClose = key => {
- if (key) {
- this.setState({
- collapseKey: key
- });
- } else {
- this.setState({
- collapseKey: '1',
- currColEnvObj: {}
- });
- }
- };
- openReport = id => {
- if (!this.reports[id]) {
- return message.warn('还没有生成报告');
- }
- this.setState({ visible: true, curCaseid: id });
- };
- openAdv = id => {
- let findCase = _.find(this.props.currCaseList, item => item.id === id);
- this.setState({
- enableScript: findCase.enable_script,
- curScript: findCase.test_script,
- advVisible: true,
- curCaseid: id
- });
- };
- handleScriptChange = d => {
- this.setState({ curScript: d.text });
- };
- handleAdvCancel = () => {
- this.setState({ advVisible: false });
- };
- handleAdvOk = async () => {
- const { curCaseid, enableScript, curScript } = this.state;
- const res = await axios.post('/api/col/up_case', {
- id: curCaseid,
- test_script: curScript,
- enable_script: enableScript
- });
- if (res.data.errcode === 0) {
- message.success('更新成功');
- }
- this.setState({ advVisible: false });
- let currColId = this.currColId;
- this.props.setColData({
- currColId: +currColId,
- isShowCol: true,
- isRander: false
- });
- await this.props.fetchCaseList(currColId);
- this.handleColdata(this.props.currCaseList);
- };
- handleCancel = () => {
- this.setState({ visible: false });
- };
- currProjectEnvChange = (envName, project_id) => {
- let currColEnvObj = {
- ...this.state.currColEnvObj,
- [project_id]: envName
- };
- this.setState({ currColEnvObj });
- // this.handleColdata(this.props.currCaseList, envName, project_id);
- this.handleColdata(this.props.currCaseList,currColEnvObj);
- };
- autoTests = () => {
- this.setState({ autoVisible: true, currColEnvObj: {}, collapseKey: '' });
- };
- handleAuto = () => {
- this.setState({
- autoVisible: false,
- email: false,
- download: false,
- mode: 'html',
- currColEnvObj: {},
- collapseKey: ''
- });
- };
- copyUrl = url => {
- copy(url);
- message.success('已经成功复制到剪切板');
- };
- modeChange = mode => {
- this.setState({ mode });
- };
- emailChange = email => {
- this.setState({ email });
- };
- downloadChange = download => {
- this.setState({ download });
- };
- handleColEnvObj = envObj => {
- let str = '';
- for (let key in envObj) {
- str += envObj[key] ? `&env_${key}=${envObj[key]}` : '';
- }
- return str;
- };
- handleCommonSetting = ()=>{
- let setting = this.state.commonSetting;
- let params = {
- col_id: this.props.currColId,
- ...setting
- };
- console.log(params)
- axios.post('/api/col/up_col', params).then(async res => {
- if (res.data.errcode) {
- return message.error(res.data.errmsg);
- }
- message.success('配置测试集成功');
- });
- this.setState({
- commonSettingModalVisible: false
- })
- }
- cancelCommonSetting = ()=>{
- this.setState({
- commonSettingModalVisible: false
- })
- }
- openCommonSetting = ()=>{
- this.setState({
- commonSettingModalVisible: true
- })
- }
- changeCommonFieldSetting = (key)=>{
- return (e)=>{
- let value = e;
- if(typeof e === 'object' && e){
- value = e.target.value;
- }
- let {checkResponseField} = this.state.commonSetting;
- this.setState({
- commonSetting: {
- ...this.state.commonSetting,
- checkResponseField: {
- ...checkResponseField,
- [key]: value
- }
- }
- })
- }
- }
-
- render() {
- const currProjectId = this.props.currProject._id;
- const columns = [
- {
- property: 'casename',
- header: {
- label: '用例名称'
- },
- props: {
- style: {
- width: '250px'
- }
- },
- cell: {
- formatters: [
- (text, { rowData }) => {
- let record = rowData;
- return (
- <Link to={'/project/' + currProjectId + '/interface/case/' + record._id}>
- {record.casename.length > 23
- ? record.casename.substr(0, 20) + '...'
- : record.casename}
- </Link>
- );
- }
- ]
- }
- },
- {
- header: {
- label: 'key',
- formatters: [
- () => {
- return (
- <Tooltip
- title={
- <span>
- {' '}
- 每个用例都有唯一的key,用于获取所匹配接口的响应数据,例如使用{' '}
- <a
- href="https://hellosean1025.github.io/yapi/documents/case.html#%E7%AC%AC%E4%BA%8C%E6%AD%A5%EF%BC%8C%E7%BC%96%E8%BE%91%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B"
- className="link-tooltip"
- target="blank"
- >
- {' '}
- 变量参数{' '}
- </a>{' '}
- 功能{' '}
- </span>
- }
- >
- Key
- </Tooltip>
- );
- }
- ]
- },
- props: {
- style: {
- width: '100px'
- }
- },
- cell: {
- formatters: [
- (value, { rowData }) => {
- return <span>{rowData._id}</span>;
- }
- ]
- }
- },
- {
- property: 'test_status',
- header: {
- label: '状态'
- },
- props: {
- style: {
- width: '100px'
- }
- },
- cell: {
- formatters: [
- (value, { rowData }) => {
- let id = rowData._id;
- let code = this.reports[id] ? this.reports[id].code : 0;
- if (rowData.test_status === 'loading') {
- return (
- <div>
- <Spin />
- </div>
- );
- }
- switch (code) {
- case 0:
- return (
- <div>
- <Tooltip title="Pass">
- <Icon
- style={{
- color: '#00a854'
- }}
- type="check-circle"
- />
- </Tooltip>
- </div>
- );
- case 400:
- return (
- <div>
- <Tooltip title="请求异常">
- <Icon
- type="info-circle"
- style={{
- color: '#f04134'
- }}
- />
- </Tooltip>
- </div>
- );
- case 1:
- return (
- <div>
- <Tooltip title="验证失败">
- <Icon
- type="exclamation-circle"
- style={{
- color: '#ffbf00'
- }}
- />
- </Tooltip>
- </div>
- );
- default:
- return (
- <div>
- <Icon
- style={{
- color: '#00a854'
- }}
- type="check-circle"
- />
- </div>
- );
- }
- }
- ]
- }
- },
- {
- property: 'path',
- header: {
- label: '接口路径'
- },
- cell: {
- formatters: [
- (text, { rowData }) => {
- let record = rowData;
- return (
- <Tooltip title="跳转到对应接口">
- <Link to={`/project/${record.project_id}/interface/api/${record.interface_id}`}>
- {record.path.length > 23 ? record.path + '...' : record.path}
- </Link>
- </Tooltip>
- );
- }
- ]
- }
- },
- {
- header: {
- label: '测试报告'
- },
- props: {
- style: {
- width: '200px'
- }
- },
- cell: {
- formatters: [
- (text, { rowData }) => {
- let reportFun = () => {
- if (!this.reports[rowData.id]) {
- return null;
- }
- return <Button onClick={() => this.openReport(rowData.id)}>测试报告</Button>;
- };
- return <div className="interface-col-table-action">{reportFun()}</div>;
- }
- ]
- }
- }
- ];
- const { rows } = this.state;
- const components = {
- header: {
- cell: dnd.Header
- },
- body: {
- row: dnd.Row
- }
- };
- const resolvedColumns = resolve.columnChildren({ columns });
- const resolvedRows = resolve.resolve({ columns: resolvedColumns, method: resolve.nested })(
- rows
- );
- const localUrl =
- location.protocol +
- '//' +
- location.hostname +
- (location.port !== '' ? ':' + location.port : '');
- let currColEnvObj = this.handleColEnvObj(this.state.currColEnvObj);
- const autoTestsUrl = `/api/open/run_auto_test?id=${this.props.currColId}&token=${
- this.props.token
- }${currColEnvObj ? currColEnvObj : ''}&mode=${this.state.mode}&email=${
- this.state.email
- }&download=${this.state.download}`;
- let col_name = '';
- let col_desc = '';
- for (var i = 0; i < this.props.interfaceColList.length; i++) {
- if (this.props.interfaceColList[i]._id === this.props.currColId) {
- col_name = this.props.interfaceColList[i].name;
- col_desc = this.props.interfaceColList[i].desc;
- break;
- }
- }
- return (
- <div className="interface-col">
- <Modal
- title="通用规则配置"
- visible={this.state.commonSettingModalVisible}
- onOk={this.handleCommonSetting}
- onCancel={this.cancelCommonSetting}
- width={'1000px'}
- style={defaultModalStyle}
- >
- <div className="common-setting-modal">
- <Row className="setting-item">
- <Col className="col-item" span="4">
- <label>检查HttpCode: <Tooltip title={'检查 http code 是否为 200'}>
- <Icon type="question-circle-o" style={{ width: '10px' }} />
- </Tooltip></label>
- </Col>
- <Col className="col-item" span="18">
- <Switch onChange={e=>{
- let {commonSetting} = this.state;
- this.setState({
- commonSetting :{
- ...commonSetting,
- checkHttpCodeIs200: e
- }
- })
- }} checked={this.state.commonSetting.checkHttpCodeIs200} checkedChildren="开" unCheckedChildren="关" />
- </Col>
- </Row>
- <Row className="setting-item">
- <Col className="col-item" span="4">
- <label>检查返回json: <Tooltip title={'检查接口返回数据字段值,比如检查 code 是不是等于 0'}>
- <Icon type="question-circle-o" style={{ width: '10px' }} />
- </Tooltip></label>
- </Col>
- <Col className="col-item" span="6">
- <Input value={this.state.commonSetting.checkResponseField.name} onChange={this.changeCommonFieldSetting('name')} placeholder="字段名" />
- </Col>
- <Col className="col-item" span="6">
- <Input onChange={this.changeCommonFieldSetting('value')} value={this.state.commonSetting.checkResponseField.value} placeholder="值" />
- </Col>
- <Col className="col-item" span="6">
- <Switch onChange={this.changeCommonFieldSetting('enable')} checked={this.state.commonSetting.checkResponseField.enable} checkedChildren="开" unCheckedChildren="关" />
- </Col>
- </Row>
- <Row className="setting-item">
- <Col className="col-item" span="4">
- <label>检查返回数据结构: <Tooltip title={'只有 response 基于 json-schema 方式定义,该检查才会生效'}>
- <Icon type="question-circle-o" style={{ width: '10px' }} />
- </Tooltip></label>
- </Col>
- <Col className="col-item" span="18">
- <Switch onChange={e=>{
- let {commonSetting} = this.state;
- this.setState({
- commonSetting :{
- ...commonSetting,
- checkResponseSchema: e
- }
- })
- }} checked={this.state.commonSetting.checkResponseSchema} checkedChildren="开" unCheckedChildren="关" />
- </Col>
- </Row>
- <Row className="setting-item">
- <Col className="col-item " span="4">
- <label>全局测试脚本: <Tooltip title={'在跑自动化测试时,优先调用全局脚本,只有全局脚本通过测试,才会开始跑case自定义的测试脚本'}>
- <Icon type="question-circle-o" style={{ width: '10px' }} />
- </Tooltip></label>
- </Col>
- <Col className="col-item" span="14">
- <div><Switch onChange={e=>{
- let {commonSetting} = this.state;
- this.setState({
- commonSetting :{
- ...commonSetting,
- checkScript: {
- ...this.state.checkScript,
- enable: e
- }
- }
- })
- }} checked={this.state.commonSetting.checkScript.enable} checkedChildren="开" unCheckedChildren="关" /></div>
- <AceEditor
- onChange={this.onChangeTest}
- className="case-script"
- data={this.state.commonSetting.checkScript.content}
- 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>
- </div>
- </Modal>
- <Row type="flex" justify="center" align="top">
- <Col span={5}>
- <h2
- className="interface-title"
- style={{
- display: 'inline-block',
- margin: '8px 20px 16px 0px'
- }}
- >
- 测试集合 <a
- target="_blank"
- rel="noopener noreferrer"
- href="https://hellosean1025.github.io/yapi/documents/case.html"
- >
- <Tooltip title="点击查看文档">
- <Icon type="question-circle-o" />
- </Tooltip>
- </a>
- </h2>
- </Col>
- <Col span={10}>
- <CaseEnv
- envList={this.props.envList}
- currProjectEnvChange={this.currProjectEnvChange}
- envValue={this.state.currColEnvObj}
- collapseKey={this.state.collapseKey}
- changeClose={this.changeCollapseClose}
- />
- </Col>
- <Col span={9}>
- {this.state.hasPlugin ? (
- <div
- style={{
- float: 'right',
- paddingTop: '8px'
- }}
- >
- {this.props.curProjectRole !== 'guest' && (
- <Tooltip title="在 YApi 服务端跑自动化测试,测试环境不能为私有网络,请确保 YApi 服务器可以访问到自动化测试环境domain">
- <Button
- style={{
- marginRight: '8px'
- }}
- onClick={this.autoTests}
- >
- 服务端测试
- </Button>
- </Tooltip>
- )}
- <Button onClick={this.openCommonSetting} style={{
- marginRight: '8px'
- }} >通用规则配置</Button>
-
- <Button type="primary" onClick={this.executeTests}>
- 开始测试
- </Button>
- </div>
- ) : (
- <Tooltip title="请安装 cross-request Chrome 插件">
- <Button
- disabled
- type="primary"
- style={{
- float: 'right',
- marginTop: '8px'
- }}
- >
- 开始测试
- </Button>
- </Tooltip>
- )}
- </Col>
- </Row>
- <div className="component-label-wrapper">
- <Label onChange={val => this.handleChangeInterfaceCol(val, col_name)} desc={col_desc} />
- </div>
- <Table.Provider
- components={components}
- columns={resolvedColumns}
- style={{
- width: '100%',
- borderCollapse: 'collapse'
- }}
- >
- <Table.Header
- className="interface-col-table-header"
- headerRows={resolve.headerRows({ columns })}
- />
- <Table.Body
- className="interface-col-table-body"
- rows={resolvedRows}
- rowKey="id"
- onRow={this.onRow}
- />
- </Table.Provider>
- <Modal
- title="测试报告"
- width="900px"
- style={{
- minHeight: '500px'
- }}
- visible={this.state.visible}
- onCancel={this.handleCancel}
- footer={null}
- >
- <CaseReport {...this.reports[this.state.curCaseid]} />
- </Modal>
- <Modal
- title="自定义测试脚本"
- width="660px"
- style={{
- minHeight: '500px'
- }}
- visible={this.state.advVisible}
- onCancel={this.handleAdvCancel}
- onOk={this.handleAdvOk}
- maskClosable={false}
- >
- <h3>
- 是否开启:
- <Switch
- checked={this.state.enableScript}
- onChange={e => this.setState({ enableScript: e })}
- />
- </h3>
- <AceEditor
- className="case-script"
- data={this.state.curScript}
- onChange={this.handleScriptChange}
- />
- </Modal>
- {this.state.autoVisible && (
- <Modal
- title="服务端自动化测试"
- width="780px"
- style={{
- minHeight: '500px'
- }}
- visible={this.state.autoVisible}
- onCancel={this.handleAuto}
- className="autoTestsModal"
- footer={null}
- >
- <Row type="flex" justify="space-around" className="row" align="top">
- <Col span={3} className="label" style={{ paddingTop: '16px' }}>
- 选择环境
- <Tooltip title="默认使用测试用例选择的环境">
- <Icon type="question-circle-o" />
- </Tooltip>
- :
- </Col>
- <Col span={21}>
- <CaseEnv
- envList={this.props.envList}
- currProjectEnvChange={this.currProjectEnvChange}
- envValue={this.state.currColEnvObj}
- collapseKey={this.state.collapseKey}
- changeClose={this.changeCollapseClose}
- />
- </Col>
- </Row>
- <Row type="flex" justify="space-around" className="row" align="middle">
- <Col span={3} className="label">
- 输出格式:
- </Col>
- <Col span={21}>
- <Select value={this.state.mode} onChange={this.modeChange}>
- <Option key="html" value="html">
- html
- </Option>
- <Option key="json" value="json">
- json
- </Option>
- </Select>
- </Col>
- </Row>
- <Row type="flex" justify="space-around" className="row" align="middle">
- <Col span={3} className="label">
- 消息通知
- <Tooltip title={'测试不通过时,会给项目组成员发送消息通知'}>
- <Icon
- type="question-circle-o"
- style={{
- width: '10px'
- }}
- />
- </Tooltip>
- :
- </Col>
- <Col span={21}>
- <Switch
- checked={this.state.email}
- checkedChildren="开"
- unCheckedChildren="关"
- onChange={this.emailChange}
- />
- </Col>
- </Row>
- <Row type="flex" justify="space-around" className="row" align="middle">
- <Col span={3} className="label">
- 下载数据
- <Tooltip title={'开启后,测试数据将被下载到本地'}>
- <Icon
- type="question-circle-o"
- style={{
- width: '10px'
- }}
- />
- </Tooltip>
- :
- </Col>
- <Col span={21}>
- <Switch
- checked={this.state.download}
- checkedChildren="开"
- unCheckedChildren="关"
- onChange={this.downloadChange}
- />
- </Col>
- </Row>
- <Row type="flex" justify="space-around" className="row" align="middle">
- <Col span={21} className="autoTestUrl">
- <a
- target="_blank"
- rel="noopener noreferrer"
- href={localUrl + autoTestsUrl} >
- {autoTestsUrl}
- </a>
- </Col>
- <Col span={3}>
- <Button className="copy-btn" onClick={() => this.copyUrl(localUrl + autoTestsUrl)}>
- 复制
- </Button>
- </Col>
- </Row>
- <div className="autoTestMsg">
- 注:访问该URL,可以测试所有用例,请确保YApi服务器可以访问到环境配置的 domain
- </div>
- </Modal>
- )}
- </div>
- );
- }
- }
- export default InterfaceColContent;
|