mirror of
https://github.com/YMFE/yapi.git
synced 2025-04-12 15:10:23 +08:00
feat: 测试集合环境变量后端版本
This commit is contained in:
parent
eaef3031b9
commit
5f99f4368f
@ -109,7 +109,8 @@ class InterfaceColContent extends Component {
|
||||
enableScript: false,
|
||||
autoVisible: false,
|
||||
mode: 'html',
|
||||
email: false
|
||||
email: false,
|
||||
currColEnvObj: {}
|
||||
|
||||
};
|
||||
this.onRow = this.onRow.bind(this);
|
||||
@ -488,10 +489,11 @@ class InterfaceColContent extends Component {
|
||||
// this.setState({
|
||||
// [id]: envName
|
||||
// });
|
||||
// let currColEnvObj = {
|
||||
// ...this.state.currColEnvObj,
|
||||
// [id]: envName
|
||||
// }
|
||||
let currColEnvObj = {
|
||||
...this.state.currColEnvObj,
|
||||
[project_id]: envName
|
||||
}
|
||||
this.setState({currColEnvObj})
|
||||
this.handleColdata(this.props.currCaseList, envName, project_id)
|
||||
|
||||
};
|
||||
@ -527,6 +529,15 @@ class InterfaceColContent extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
handleColEnvObj = envObj => {
|
||||
|
||||
let str = ''
|
||||
for(let key in envObj) {
|
||||
str += envObj[key] ? `&env_${key}= ${envObj[key]}`: ''
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
render() {
|
||||
// console.log('rows',this.props.currProject);
|
||||
const currProjectId = this.props.currProject._id;
|
||||
@ -719,12 +730,13 @@ class InterfaceColContent extends Component {
|
||||
'//' +
|
||||
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
|
||||
}${this.state.currColEnv ? '&env_name=' + this.state.currColEnv : ''}&mode=${
|
||||
}${currColEnvObj ? currColEnvObj : ''}&mode=${
|
||||
this.state.mode
|
||||
}&email=${this.state.email}`;
|
||||
// console.log('projectList', this.props.projectList)
|
||||
|
||||
|
||||
return (
|
||||
<div className="interface-col">
|
||||
|
@ -128,6 +128,7 @@ function checkNameIsExistInArray(name, arr) {
|
||||
|
||||
function handleCurrDomain(domains, case_env) {
|
||||
let currDomain = _.find(domains, item => item.name === case_env);
|
||||
|
||||
if (!currDomain) {
|
||||
currDomain = domains[0];
|
||||
}
|
||||
|
@ -2,93 +2,98 @@ const projectModel = require('../models/project.js');
|
||||
const interfaceColModel = require('../models/interfaceCol.js');
|
||||
const interfaceCaseModel = require('../models/interfaceCase.js');
|
||||
const interfaceModel = require('../models/interface.js');
|
||||
const interfaceCatModel = require('../models/interfaceCat.js')
|
||||
const interfaceCatModel = require('../models/interfaceCat.js');
|
||||
const followModel = require('../models/follow.js');
|
||||
const userModel = require('../models/user.js')
|
||||
const userModel = require('../models/user.js');
|
||||
const yapi = require('../yapi.js');
|
||||
const baseController = require('./base.js');
|
||||
const { handleParams, crossRequest, handleCurrDomain, checkNameIsExistInArray } = require('../../common/postmanLib')
|
||||
const {handleParamsValue} = require('../../common/utils.js')
|
||||
const renderToHtml = require('../utils/reportHtml')
|
||||
const axios = require('axios')
|
||||
const HanldeImportData = require('../../common/HandleImportData')
|
||||
|
||||
const {
|
||||
handleParams,
|
||||
crossRequest,
|
||||
handleCurrDomain,
|
||||
checkNameIsExistInArray
|
||||
} = require('../../common/postmanLib');
|
||||
const { handleParamsValue } = require('../../common/utils.js');
|
||||
const renderToHtml = require('../utils/reportHtml');
|
||||
const axios = require('axios');
|
||||
const HanldeImportData = require('../../common/HandleImportData');
|
||||
const _ = require('underscore');
|
||||
|
||||
/**
|
||||
* {
|
||||
* postman: require('./m')
|
||||
* }
|
||||
*/
|
||||
const importDataModule = {}
|
||||
yapi.emitHook('import_data', importDataModule)
|
||||
const importDataModule = {};
|
||||
yapi.emitHook('import_data', importDataModule);
|
||||
|
||||
class openController extends baseController{
|
||||
constructor(ctx){
|
||||
super(ctx)
|
||||
this.projectModel = yapi.getInst(projectModel)
|
||||
this.interfaceColModel = yapi.getInst(interfaceColModel)
|
||||
this.interfaceCaseModel = yapi.getInst(interfaceCaseModel)
|
||||
this.interfaceModel = yapi.getInst(interfaceModel)
|
||||
this.interfaceCatModel = yapi.getInst(interfaceCatModel)
|
||||
class openController extends baseController {
|
||||
constructor(ctx) {
|
||||
super(ctx);
|
||||
this.projectModel = yapi.getInst(projectModel);
|
||||
this.interfaceColModel = yapi.getInst(interfaceColModel);
|
||||
this.interfaceCaseModel = yapi.getInst(interfaceCaseModel);
|
||||
this.interfaceModel = yapi.getInst(interfaceModel);
|
||||
this.interfaceCatModel = yapi.getInst(interfaceCatModel);
|
||||
this.followModel = yapi.getInst(followModel);
|
||||
this.userModel = yapi.getInst(userModel)
|
||||
this.handleValue = this.handleValue.bind(this)
|
||||
this.userModel = yapi.getInst(userModel);
|
||||
this.handleValue = this.handleValue.bind(this);
|
||||
this.schemaMap = {
|
||||
runAutoTest: {
|
||||
'*id': 'number',
|
||||
'env_name': 'string',
|
||||
'project_id': "string",
|
||||
'token': 'string',
|
||||
'mode' : {
|
||||
project_id: 'string',
|
||||
token: 'string',
|
||||
mode: {
|
||||
type: 'string',
|
||||
default: 'html'
|
||||
},
|
||||
'email' : {
|
||||
email: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
},
|
||||
closeRemoveAdditional: true
|
||||
},
|
||||
importData: {
|
||||
'*type': 'string',
|
||||
'url': 'string',
|
||||
url: 'string',
|
||||
'*token': 'string',
|
||||
'json': 'string',
|
||||
'project_id': "string",
|
||||
"merge": {
|
||||
json: 'string',
|
||||
project_id: 'string',
|
||||
merge: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async importData(ctx){
|
||||
async importData(ctx) {
|
||||
let type = ctx.params.type;
|
||||
let url = ctx.params.url;
|
||||
let content = ctx.params.json;
|
||||
let project_id = ctx.params.project_id;
|
||||
let dataSync = ctx.params.merge;
|
||||
let token = ctx.params.token;
|
||||
if(!type || !importDataModule[type]){
|
||||
return ctx.body = yapi.commons.resReturn(null, 40022, '不存在的导入方式');
|
||||
if (!type || !importDataModule[type]) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, '不存在的导入方式'));
|
||||
}
|
||||
|
||||
if(!content){
|
||||
return ctx.body = yapi.commons.resReturn(null, 40022, 'json 不能为空');
|
||||
if (!content) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, 'json 不能为空'));
|
||||
}
|
||||
try{
|
||||
content = JSON.parse(content)
|
||||
}catch(e){
|
||||
return ctx.body = yapi.commons.resReturn(null, 40022, 'json 格式有误');
|
||||
try {
|
||||
content = JSON.parse(content);
|
||||
} catch (e) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, 'json 格式有误'));
|
||||
}
|
||||
|
||||
let menuList = await this.interfaceCatModel.list(project_id)
|
||||
let menuList = await this.interfaceCatModel.list(project_id);
|
||||
let selectCatid = menuList[0]._id;
|
||||
let projectData = await this.projectModel.get(project_id)
|
||||
let res = await importDataModule[type](content)
|
||||
let projectData = await this.projectModel.get(project_id);
|
||||
let res = await importDataModule[type](content);
|
||||
|
||||
let successMessage;
|
||||
let errorMessage = []
|
||||
let errorMessage = [];
|
||||
let data = await HanldeImportData(
|
||||
res,
|
||||
project_id,
|
||||
@ -96,110 +101,128 @@ class openController extends baseController{
|
||||
menuList,
|
||||
projectData.basePath,
|
||||
dataSync,
|
||||
(err)=>{
|
||||
errorMessage.push(err)
|
||||
},
|
||||
(msg)=>{
|
||||
successMessage = msg
|
||||
},
|
||||
()=> {},
|
||||
err => {
|
||||
errorMessage.push(err);
|
||||
},
|
||||
msg => {
|
||||
successMessage = msg;
|
||||
},
|
||||
() => {},
|
||||
token,
|
||||
yapi.WEBCONFIG.port
|
||||
)
|
||||
);
|
||||
|
||||
if(errorMessage.length > 0){
|
||||
return ctx.body = yapi.commons.resReturn(null, 404, errorMessage.join("\n"))
|
||||
if (errorMessage.length > 0) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 404, errorMessage.join('\n')));
|
||||
}
|
||||
ctx.body = yapi.commons.resReturn(null, 0, successMessage)
|
||||
ctx.body = yapi.commons.resReturn(null, 0, successMessage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
async projectInterfaceData(ctx){
|
||||
ctx.body = 'projectInterfaceData'
|
||||
async projectInterfaceData(ctx) {
|
||||
ctx.body = 'projectInterfaceData';
|
||||
}
|
||||
|
||||
handleValue(val){
|
||||
handleValue(val) {
|
||||
return handleParamsValue(val, this.records);
|
||||
}
|
||||
|
||||
async runAutoTest(ctx){
|
||||
handleEvnParams(params) {
|
||||
let result = [];
|
||||
Object.keys(params).map(item => {
|
||||
if (/env_/gi.test(item)) {
|
||||
let curEnv = yapi.commons.trim(params[item])
|
||||
let value = { curEnv, project_id: item.split('_')[1] };
|
||||
result.push(value);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
async runAutoTest(ctx) {
|
||||
const projectId = ctx.params.project_id;
|
||||
const startTime = new Date().getTime();
|
||||
const records = this.records = {};
|
||||
const reports = this.reports = {};
|
||||
const testList = []
|
||||
const records = (this.records = {});
|
||||
const reports = (this.reports = {});
|
||||
const testList = [];
|
||||
let id = ctx.params.id;
|
||||
let curEnv = ctx.params.env_name;
|
||||
let curEnvList = this.handleEvnParams(ctx.params);
|
||||
// console.log('curEnvList', curEnvList);
|
||||
// let curEnv = ctx.params.env_name;
|
||||
let colData = await this.interfaceColModel.get(id);
|
||||
if(!colData){
|
||||
return ctx.body = yapi.commons.resReturn(null, 40022, 'id值不存在');
|
||||
}
|
||||
|
||||
if (!colData) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, 'id值不存在'));
|
||||
}
|
||||
|
||||
let projectData = await this.projectModel.get(projectId);
|
||||
|
||||
|
||||
|
||||
let caseList = await yapi.commons.getCaseList(id);
|
||||
if(caseList.errcode !== 0){
|
||||
ctx.body = caseList
|
||||
if (caseList.errcode !== 0) {
|
||||
ctx.body = caseList;
|
||||
}
|
||||
caseList = caseList.data;
|
||||
for(let i=0, l= caseList.length; i< l; i++){
|
||||
for (let i = 0, l = caseList.length; i < l; i++) {
|
||||
let item = caseList[i];
|
||||
let projectEvn = await this.projectModel.getByEnv(item.project_id)
|
||||
|
||||
let projectEvn = await this.projectModel.getByEnv(item.project_id);
|
||||
|
||||
item.id = item._id;
|
||||
let curEnvItem = _.find(curEnvList, key => {
|
||||
return key.project_id == item.project_id;
|
||||
});
|
||||
|
||||
item.case_env = curEnv || item.case_env;
|
||||
item.req_headers = this.handleReqHeader(item.req_headers, projectData.env, item.case_env)
|
||||
|
||||
item.case_env = curEnvItem ? curEnvItem.curEnv || item.case_env : item.case_env;
|
||||
item.req_headers = this.handleReqHeader(item.req_headers, projectEvn.env, item.case_env);
|
||||
item.pre_script = projectData.pre_script;
|
||||
item.after_script = projectData.after_script;
|
||||
item.env= projectEvn.env;
|
||||
item.env = projectEvn.env;
|
||||
let result;
|
||||
try{
|
||||
// console.log('item',item.case_env)
|
||||
try {
|
||||
result = await this.handleTest(item);
|
||||
}catch(err){
|
||||
} catch (err) {
|
||||
result = err;
|
||||
}
|
||||
|
||||
|
||||
reports[item.id] = result;
|
||||
records[item.id] = {
|
||||
params: result.params,
|
||||
body: result.res_body
|
||||
}
|
||||
testList.push(result)
|
||||
};
|
||||
testList.push(result);
|
||||
}
|
||||
|
||||
function getMessage(testList){
|
||||
let successNum = 0, failedNum = 0, len = 0, msg='';
|
||||
testList.forEach(item=>{
|
||||
function getMessage(testList) {
|
||||
let successNum = 0,
|
||||
failedNum = 0,
|
||||
len = 0,
|
||||
msg = '';
|
||||
testList.forEach(item => {
|
||||
len++;
|
||||
if(item.code ===0) successNum++;
|
||||
if (item.code === 0) successNum++;
|
||||
else failedNum++;
|
||||
})
|
||||
if(failedNum === 0){
|
||||
msg= `一共 ${len} 测试用例,全部验证通过`
|
||||
} else{
|
||||
msg= `一共 ${len} 测试用例,${successNum} 个验证通过, ${failedNum} 个未通过。`
|
||||
});
|
||||
if (failedNum === 0) {
|
||||
msg = `一共 ${len} 测试用例,全部验证通过`;
|
||||
} else {
|
||||
msg = `一共 ${len} 测试用例,${successNum} 个验证通过, ${failedNum} 个未通过。`;
|
||||
}
|
||||
|
||||
|
||||
return { msg, len, successNum, failedNum }
|
||||
return { msg, len, successNum, failedNum };
|
||||
}
|
||||
|
||||
const endTime = new Date().getTime();
|
||||
const executionTime = (endTime - startTime)/1000;
|
||||
const executionTime = (endTime - startTime) / 1000;
|
||||
|
||||
let reportsResult = {
|
||||
message: getMessage(testList),
|
||||
runTime: executionTime + 's',
|
||||
numbs: testList.length,
|
||||
list: testList
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (ctx.params.email === true && reportsResult.message.failedNum !== 0) {
|
||||
let autoTestUrl = `http://${ctx.request.host}/api/open/run_auto_test?id=${id}&token=${token}&mode=${ctx.params.mode}`
|
||||
let autoTestUrl = `http://${
|
||||
ctx.request.host
|
||||
}/api/open/run_auto_test?id=${id}&token=${token}&mode=${ctx.params.mode}`;
|
||||
this.sendNotice(projectId, {
|
||||
title: `YApi自动化测试报告`,
|
||||
content: `
|
||||
@ -216,21 +239,20 @@ class openController extends baseController{
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if(ctx.params.mode === 'json'){
|
||||
return ctx.body = reportsResult
|
||||
}else{
|
||||
return ctx.body = renderToHtml(reportsResult)
|
||||
if (ctx.params.mode === 'json') {
|
||||
return (ctx.body = reportsResult);
|
||||
} else {
|
||||
return (ctx.body = renderToHtml(reportsResult));
|
||||
}
|
||||
}
|
||||
|
||||
async handleTest(interfaceData){
|
||||
async handleTest(interfaceData) {
|
||||
let requestParams = {};
|
||||
let options;
|
||||
options = handleParams(interfaceData, this.handleValue, requestParams)
|
||||
options = handleParams(interfaceData, this.handleValue, requestParams);
|
||||
let result = {
|
||||
id: interfaceData.id,
|
||||
name: interfaceData.casename,
|
||||
@ -239,37 +261,34 @@ class openController extends baseController{
|
||||
validRes: []
|
||||
};
|
||||
try {
|
||||
let data = await crossRequest(options, interfaceData.pre_script, interfaceData.after_script)
|
||||
let res= data.res;
|
||||
|
||||
result = Object.assign(
|
||||
result,
|
||||
{
|
||||
status: res.status,
|
||||
statusText: res.statusText,
|
||||
url: data.req.url,
|
||||
method: data.req.method,
|
||||
data: data.req.data,
|
||||
headers: data.req.headers,
|
||||
res_header: res.header,
|
||||
res_body: res.body
|
||||
}
|
||||
)
|
||||
let data = await crossRequest(options, interfaceData.pre_script, interfaceData.after_script);
|
||||
let res = data.res;
|
||||
|
||||
result = Object.assign(result, {
|
||||
status: res.status,
|
||||
statusText: res.statusText,
|
||||
url: data.req.url,
|
||||
method: data.req.method,
|
||||
data: data.req.data,
|
||||
headers: data.req.headers,
|
||||
res_header: res.header,
|
||||
res_body: res.body
|
||||
});
|
||||
if (options.data && typeof options.data === 'object') {
|
||||
requestParams = Object.assign(
|
||||
requestParams,
|
||||
options.data
|
||||
)
|
||||
requestParams = Object.assign(requestParams, options.data);
|
||||
}
|
||||
|
||||
let validRes = [];
|
||||
|
||||
let responseData = Object.assign({}, {
|
||||
status: res.status,
|
||||
body: res.body,
|
||||
header: res.header,
|
||||
statusText: res.statusText
|
||||
})
|
||||
let responseData = Object.assign(
|
||||
{},
|
||||
{
|
||||
status: res.status,
|
||||
body: res.body,
|
||||
header: res.header,
|
||||
statusText: res.statusText
|
||||
}
|
||||
);
|
||||
|
||||
await this.handleScriptTest(interfaceData, responseData, validRes, requestParams);
|
||||
result.params = requestParams;
|
||||
@ -280,19 +299,14 @@ class openController extends baseController{
|
||||
result.code = 1;
|
||||
result.validRes = validRes;
|
||||
}
|
||||
|
||||
}catch(data){
|
||||
result = Object.assign(options,
|
||||
result,
|
||||
{
|
||||
res_header: data.header,
|
||||
res_body: data.body || data.message,
|
||||
status: null,
|
||||
statusText: data.message,
|
||||
code: 400
|
||||
}
|
||||
)
|
||||
|
||||
} catch (data) {
|
||||
result = Object.assign(options, result, {
|
||||
res_header: data.header,
|
||||
res_body: data.body || data.message,
|
||||
status: null,
|
||||
statusText: data.message,
|
||||
code: 400
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -306,7 +320,7 @@ class openController extends baseController{
|
||||
const projectMenbers = projectList.members.map(item => item.uid);
|
||||
|
||||
const users = this.arrUnique(projectMenbers, starUsers);
|
||||
const usersInfo = await this.userModel.findByUids(users)
|
||||
const usersInfo = await this.userModel.findByUids(users);
|
||||
const emails = usersInfo.map(item => item.email).join(',');
|
||||
|
||||
try {
|
||||
@ -314,25 +328,21 @@ class openController extends baseController{
|
||||
to: emails,
|
||||
contents: data.content,
|
||||
subject: data.title
|
||||
})
|
||||
});
|
||||
} catch (e) {
|
||||
yapi.commons.log('邮件发送失败:' + e, 'error')
|
||||
yapi.commons.log('邮件发送失败:' + e, 'error');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
arrUnique(arr1, arr2) {
|
||||
let arr = arr1.concat(arr2);
|
||||
let res = arr.filter(function (item, index, arr) {
|
||||
let res = arr.filter(function(item, index, arr) {
|
||||
return arr.indexOf(item) === index;
|
||||
})
|
||||
});
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async handleScriptTest (interfaceData, response, validRes, requestParams){
|
||||
async handleScriptTest(interfaceData, response, validRes, requestParams) {
|
||||
if (interfaceData.enable_script !== true) {
|
||||
return null;
|
||||
}
|
||||
@ -342,37 +352,37 @@ class openController extends baseController{
|
||||
records: this.records,
|
||||
script: interfaceData.test_script,
|
||||
params: requestParams
|
||||
})
|
||||
});
|
||||
if (test.errcode !== 0) {
|
||||
test.data.logs.forEach(item => {
|
||||
validRes.push({
|
||||
message: item
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
validRes.push({
|
||||
message: 'Error: ' + err.message
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleReqHeader(req_header, envData, curEnvName){
|
||||
handleReqHeader(req_header, envData, curEnvName) {
|
||||
|
||||
let currDomain = handleCurrDomain(envData, curEnvName);
|
||||
|
||||
let header = currDomain.header;
|
||||
header.forEach(item => {
|
||||
if (!checkNameIsExistInArray(item.name, req_header)) {
|
||||
item.abled = true;
|
||||
req_header.push(item)
|
||||
req_header.push(item);
|
||||
}
|
||||
})
|
||||
req_header = req_header.filter(item=> {
|
||||
return item && typeof item === 'object'
|
||||
})
|
||||
return req_header
|
||||
});
|
||||
req_header = req_header.filter(item => {
|
||||
return item && typeof item === 'object';
|
||||
});
|
||||
return req_header;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports = openController;
|
||||
module.exports = openController;
|
||||
|
@ -222,7 +222,8 @@ module.exports = async (ctx, next) => {
|
||||
} else {
|
||||
// console.log('header', ctx.request.header['content-type'].indexOf('multipart/form-data'))
|
||||
// 处理 format-data
|
||||
if(ctx.request.header['content-type'].indexOf('multipart/form-data') > -1) {
|
||||
|
||||
if(_.isString(ctx.request.header['content-type'])&&ctx.request.header['content-type'].indexOf('multipart/form-data') > -1) {
|
||||
ctx.request.body = ctx.request.body.fields;
|
||||
}
|
||||
// console.log('body', ctx.request.body)
|
||||
|
@ -1,62 +1,55 @@
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
const yapi = require("../yapi.js");
|
||||
const sha1 = require("sha1");
|
||||
const logModel = require("../models/log.js");
|
||||
const projectModel = require("../models/project.js");
|
||||
const interfaceColModel = require("../models/interfaceCol.js");
|
||||
const interfaceCaseModel = require("../models/interfaceCase.js");
|
||||
const interfaceModel = require("../models/interface.js");
|
||||
const json5 = require("json5");
|
||||
const _ = require("underscore");
|
||||
const Ajv = require("ajv");
|
||||
const Mock = require('mockjs')
|
||||
const ajv = new Ajv({
|
||||
allErrors: true,
|
||||
coerceTypes: true,
|
||||
useDefaults: true,
|
||||
removeAdditional: true
|
||||
});
|
||||
var localize = require("ajv-i18n");
|
||||
const ejs = require("easy-json-schema");
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const yapi = require('../yapi.js');
|
||||
const sha1 = require('sha1');
|
||||
const logModel = require('../models/log.js');
|
||||
const projectModel = require('../models/project.js');
|
||||
const interfaceColModel = require('../models/interfaceCol.js');
|
||||
const interfaceCaseModel = require('../models/interfaceCase.js');
|
||||
const interfaceModel = require('../models/interface.js');
|
||||
const json5 = require('json5');
|
||||
const _ = require('underscore');
|
||||
const Ajv = require('ajv');
|
||||
const Mock = require('mockjs');
|
||||
|
||||
const jsf = require('json-schema-faker');
|
||||
const formats = require('../../common/formats')
|
||||
const ejs = require('easy-json-schema');
|
||||
|
||||
const jsf = require('json-schema-faker');
|
||||
const formats = require('../../common/formats');
|
||||
const defaultOptions = {
|
||||
failOnInvalidTypes: false,
|
||||
failOnInvalidFormat: false
|
||||
}
|
||||
};
|
||||
|
||||
formats.forEach(item=>{
|
||||
formats.forEach(item => {
|
||||
item = item.name;
|
||||
jsf.format(item, ()=>{
|
||||
if(item === 'mobile'){
|
||||
return jsf.random.randexp('^[1][34578][0-9]{9}$')
|
||||
jsf.format(item, () => {
|
||||
if (item === 'mobile') {
|
||||
return jsf.random.randexp('^[1][34578][0-9]{9}$');
|
||||
}
|
||||
return Mock.mock('@'+ item)
|
||||
})
|
||||
})
|
||||
return Mock.mock('@' + item);
|
||||
});
|
||||
});
|
||||
|
||||
exports.schemaToJson = function(schema, options={}){
|
||||
Object.assign(options, defaultOptions)
|
||||
exports.schemaToJson = function(schema, options = {}) {
|
||||
Object.assign(options, defaultOptions);
|
||||
jsf.option(options);
|
||||
let result
|
||||
try{
|
||||
result = jsf(schema)
|
||||
|
||||
}catch(err){
|
||||
result = err.message
|
||||
let result;
|
||||
try {
|
||||
result = jsf(schema);
|
||||
} catch (err) {
|
||||
result = err.message;
|
||||
}
|
||||
jsf.option(defaultOptions)
|
||||
jsf.option(defaultOptions);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
exports.resReturn = (data, num, errmsg) => {
|
||||
num = num || 0;
|
||||
|
||||
return {
|
||||
errcode: num,
|
||||
errmsg: errmsg || "成功!",
|
||||
errmsg: errmsg || '成功!',
|
||||
data: data
|
||||
};
|
||||
};
|
||||
@ -66,18 +59,18 @@ exports.log = (msg, type) => {
|
||||
return;
|
||||
}
|
||||
|
||||
type = type || "log";
|
||||
type = type || 'log';
|
||||
|
||||
let f;
|
||||
|
||||
switch (type) {
|
||||
case "log":
|
||||
case 'log':
|
||||
f = console.log; // eslint-disable-line
|
||||
break;
|
||||
case "warn":
|
||||
case 'warn':
|
||||
f = console.warn; // eslint-disable-line
|
||||
break;
|
||||
case "error":
|
||||
case 'error':
|
||||
f = console.error; // eslint-disable-line
|
||||
break;
|
||||
default:
|
||||
@ -85,15 +78,15 @@ exports.log = (msg, type) => {
|
||||
break;
|
||||
}
|
||||
|
||||
f(type + ":", msg);
|
||||
f(type + ':', msg);
|
||||
|
||||
let date = new Date();
|
||||
let year = date.getFullYear();
|
||||
let month = date.getMonth() + 1;
|
||||
|
||||
let logfile = path.join(yapi.WEBROOT_LOG, year + "-" + month + ".log");
|
||||
let logfile = path.join(yapi.WEBROOT_LOG, year + '-' + month + '.log');
|
||||
|
||||
if (typeof msg === "object") {
|
||||
if (typeof msg === 'object') {
|
||||
if (msg instanceof Error) msg = msg.message;
|
||||
else msg = JSON.stringify(msg);
|
||||
}
|
||||
@ -102,7 +95,7 @@ exports.log = (msg, type) => {
|
||||
let data = `[ ${new Date().toLocaleString()} ] [ ${type} ] ${msg}\n`;
|
||||
|
||||
fs.writeFileSync(logfile, data, {
|
||||
flag: "a"
|
||||
flag: 'a'
|
||||
});
|
||||
};
|
||||
|
||||
@ -126,7 +119,7 @@ exports.fieldSelect = (data, field) => {
|
||||
var arr = {};
|
||||
|
||||
field.forEach(f => {
|
||||
typeof data[f] !== "undefined" && (arr[f] = data[f]);
|
||||
typeof data[f] !== 'undefined' && (arr[f] = data[f]);
|
||||
});
|
||||
|
||||
return arr;
|
||||
@ -152,9 +145,7 @@ exports.randStr = () => {
|
||||
exports.getIp = ctx => {
|
||||
let ip;
|
||||
try {
|
||||
ip = ctx.ip.match(/\d+.\d+.\d+.\d+/)
|
||||
? ctx.ip.match(/\d+.\d+.\d+.\d+/)[0]
|
||||
: "localhost";
|
||||
ip = ctx.ip.match(/\d+.\d+.\d+.\d+/) ? ctx.ip.match(/\d+.\d+.\d+.\d+/)[0] : 'localhost';
|
||||
} catch (e) {
|
||||
ip = null;
|
||||
}
|
||||
@ -173,20 +164,15 @@ exports.expireDate = day => {
|
||||
|
||||
exports.sendMail = (options, cb) => {
|
||||
if (!yapi.mail) return false;
|
||||
options.subject = options.subject
|
||||
? options.subject + "-YApi 平台"
|
||||
: "YApi 平台";
|
||||
options.subject = options.subject ? options.subject + '-YApi 平台' : 'YApi 平台';
|
||||
|
||||
cb =
|
||||
cb ||
|
||||
function(err) {
|
||||
if (err) {
|
||||
yapi.commons.log(
|
||||
"send mail " + options.to + " error," + err.message,
|
||||
"error"
|
||||
);
|
||||
yapi.commons.log('send mail ' + options.to + ' error,' + err.message, 'error');
|
||||
} else {
|
||||
yapi.commons.log("send mail " + options.to + " success");
|
||||
yapi.commons.log('send mail ' + options.to + ' success');
|
||||
}
|
||||
};
|
||||
|
||||
@ -201,7 +187,7 @@ exports.sendMail = (options, cb) => {
|
||||
cb
|
||||
);
|
||||
} catch (e) {
|
||||
yapi.commons.log(e.message, "error");
|
||||
yapi.commons.log(e.message, 'error');
|
||||
console.error(e.message); // eslint-disable-line
|
||||
}
|
||||
};
|
||||
@ -219,9 +205,9 @@ exports.filterRes = (list, rules) => {
|
||||
let filteredRes = {};
|
||||
|
||||
rules.forEach(rule => {
|
||||
if (typeof rule == "string") {
|
||||
if (typeof rule == 'string') {
|
||||
filteredRes[rule] = item[rule];
|
||||
} else if (typeof rule == "object") {
|
||||
} else if (typeof rule == 'object') {
|
||||
filteredRes[rule.alias] = item[rule.key];
|
||||
}
|
||||
});
|
||||
@ -235,18 +221,18 @@ exports.handleVarPath = (pathname, params) => {
|
||||
if (!_.find(params, { name: name })) {
|
||||
params.push({
|
||||
name: name,
|
||||
desc: ""
|
||||
desc: ''
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!pathname) return;
|
||||
if (pathname.indexOf(":") !== -1) {
|
||||
let paths = pathname.split("/"),
|
||||
if (pathname.indexOf(':') !== -1) {
|
||||
let paths = pathname.split('/'),
|
||||
name,
|
||||
i;
|
||||
for (i = 1; i < paths.length; i++) {
|
||||
if (paths[i] && paths[i][0] === ":") {
|
||||
if (paths[i] && paths[i][0] === ':') {
|
||||
name = paths[i].substr(1);
|
||||
insertParams(name);
|
||||
}
|
||||
@ -279,7 +265,7 @@ exports.verifyPath = path => {
|
||||
* a = {a: 2}
|
||||
*/
|
||||
exports.sandbox = (sandbox, script) => {
|
||||
const vm = require("vm");
|
||||
const vm = require('vm');
|
||||
sandbox = sandbox || {};
|
||||
script = new vm.Script(script);
|
||||
const context = new vm.createContext(sandbox);
|
||||
@ -294,9 +280,9 @@ function trim(str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
str = str + "";
|
||||
str = str + '';
|
||||
|
||||
return str.replace(/(^\s*)|(\s*$)/g, "");
|
||||
return str.replace(/(^\s*)|(\s*$)/g, '');
|
||||
}
|
||||
|
||||
function ltrim(str) {
|
||||
@ -304,9 +290,9 @@ function ltrim(str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
str = str + "";
|
||||
str = str + '';
|
||||
|
||||
return str.replace(/(^\s*)/g, "");
|
||||
return str.replace(/(^\s*)/g, '');
|
||||
}
|
||||
|
||||
function rtrim(str) {
|
||||
@ -314,9 +300,9 @@ function rtrim(str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
str = str + "";
|
||||
str = str + '';
|
||||
|
||||
return str.replace(/(\s*$)/g, "");
|
||||
return str.replace(/(\s*$)/g, '');
|
||||
}
|
||||
|
||||
exports.trim = trim;
|
||||
@ -330,12 +316,7 @@ exports.rtrim = rtrim;
|
||||
* @return Object {a: 'ab', b: 123}
|
||||
*/
|
||||
exports.handleParams = (params, keys) => {
|
||||
if (
|
||||
!params ||
|
||||
typeof params !== "object" ||
|
||||
!keys ||
|
||||
typeof keys !== "object"
|
||||
) {
|
||||
if (!params || typeof params !== 'object' || !keys || typeof keys !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -343,14 +324,14 @@ exports.handleParams = (params, keys) => {
|
||||
var filter = keys[key];
|
||||
if (params[key]) {
|
||||
switch (filter) {
|
||||
case "string":
|
||||
params[key] = trim(params[key] + "");
|
||||
case 'string':
|
||||
params[key] = trim(params[key] + '');
|
||||
break;
|
||||
case "number":
|
||||
case 'number':
|
||||
params[key] = !isNaN(params[key]) ? parseInt(params[key], 10) : 0;
|
||||
break;
|
||||
default:
|
||||
params[key] = trim(params + "");
|
||||
params[key] = trim(params + '');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,15 +339,29 @@ exports.handleParams = (params, keys) => {
|
||||
return params;
|
||||
};
|
||||
|
||||
exports.validateParams = (schema, params) => {
|
||||
schema = ejs(schema);
|
||||
schema.additionalProperties = false;
|
||||
exports.validateParams = (schema2, params) => {
|
||||
const flag = schema2.closeRemoveAdditional;
|
||||
const ajv = new Ajv({
|
||||
allErrors: true,
|
||||
coerceTypes: true,
|
||||
useDefaults: true,
|
||||
removeAdditional: flag ? false : true
|
||||
});
|
||||
|
||||
|
||||
var localize = require('ajv-i18n');
|
||||
delete schema2.closeRemoveAdditional;
|
||||
|
||||
const schema = ejs(schema2);
|
||||
|
||||
schema.additionalProperties = flag ? true : false;
|
||||
const validate = ajv.compile(schema);
|
||||
let valid = validate(params);
|
||||
let message = "请求参数 ";
|
||||
|
||||
let message = '请求参数 ';
|
||||
if (!valid) {
|
||||
localize.zh(validate.errors);
|
||||
message += ajv.errorsText(validate.errors, { separator: "\n" });
|
||||
message += ajv.errorsText(validate.errors, { separator: '\n' });
|
||||
}
|
||||
|
||||
return {
|
||||
@ -388,7 +383,7 @@ exports.saveLog = logData => {
|
||||
};
|
||||
logInst.save(data).then();
|
||||
} catch (e) {
|
||||
yapi.commons.log(e, "error"); // eslint-disable-line
|
||||
yapi.commons.log(e, 'error'); // eslint-disable-line
|
||||
}
|
||||
};
|
||||
|
||||
@ -402,55 +397,31 @@ exports.saveLog = logData => {
|
||||
* @param {*} action controller action_name
|
||||
* @param {*} ws enable ws
|
||||
*/
|
||||
exports.createAction = (
|
||||
router,
|
||||
baseurl,
|
||||
routerController,
|
||||
action,
|
||||
path,
|
||||
method,
|
||||
ws
|
||||
) => {
|
||||
exports.createAction = (router, baseurl, routerController, action, path, method, ws) => {
|
||||
router[method](baseurl + path, async ctx => {
|
||||
let inst = new routerController(ctx);
|
||||
try {
|
||||
await inst.init(ctx);
|
||||
if (
|
||||
inst.schemaMap &&
|
||||
typeof inst.schemaMap === "object" &&
|
||||
inst.schemaMap[action]
|
||||
) {
|
||||
ctx.params = Object.assign(
|
||||
{},
|
||||
ctx.request.query,
|
||||
ctx.request.body,
|
||||
ctx.params
|
||||
);
|
||||
let validResult = yapi.commons.validateParams(
|
||||
inst.schemaMap[action],
|
||||
ctx.params
|
||||
);
|
||||
if (inst.schemaMap && typeof inst.schemaMap === 'object' && inst.schemaMap[action]) {
|
||||
ctx.params = Object.assign({}, ctx.request.query, ctx.request.body, ctx.params);
|
||||
let validResult = yapi.commons.validateParams(inst.schemaMap[action], ctx.params);
|
||||
|
||||
if (!validResult.valid) {
|
||||
return (ctx.body = yapi.commons.resReturn(
|
||||
null,
|
||||
400,
|
||||
validResult.message
|
||||
));
|
||||
return (ctx.body = yapi.commons.resReturn(null, 400, validResult.message));
|
||||
}
|
||||
}
|
||||
if (inst.$auth === true) {
|
||||
await inst[action].call(inst, ctx);
|
||||
} else {
|
||||
if (ws === true) {
|
||||
ctx.ws.send("请登录...");
|
||||
ctx.ws.send('请登录...');
|
||||
} else {
|
||||
ctx.body = yapi.commons.resReturn(null, 40011, "请登录...");
|
||||
ctx.body = yapi.commons.resReturn(null, 40011, '请登录...');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.body = yapi.commons.resReturn(null, 40011, "服务器出错...");
|
||||
yapi.commons.log(err, "error");
|
||||
ctx.body = yapi.commons.resReturn(null, 40011, '服务器出错...');
|
||||
yapi.commons.log(err, 'error');
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -472,7 +443,7 @@ function handleParamsValue(params, val) {
|
||||
value[item.name] = item;
|
||||
});
|
||||
params.forEach((item, index) => {
|
||||
if (!value[item.name] || typeof value[item.name] !== "object") return null;
|
||||
if (!value[item.name] || typeof value[item.name] !== 'object') return null;
|
||||
params[index].value = value[item.name].value;
|
||||
if (!_.isUndefined(value[item.name].enable)) {
|
||||
params[index].enable = value[item.name].enable;
|
||||
@ -489,7 +460,7 @@ exports.getCaseList = async function getCaseList(id) {
|
||||
const projectInst = yapi.getInst(projectModel);
|
||||
const interfaceInst = yapi.getInst(interfaceModel);
|
||||
|
||||
let resultList = await caseInst.list(id, "all");
|
||||
let resultList = await caseInst.list(id, 'all');
|
||||
let colData = await colInst.get(id);
|
||||
for (let index = 0; index < resultList.length; index++) {
|
||||
let result = resultList[index].toObject();
|
||||
@ -503,15 +474,9 @@ exports.getCaseList = async function getCaseList(id) {
|
||||
result.method = data.method;
|
||||
result.title = data.title;
|
||||
result.req_body_type = data.req_body_type;
|
||||
result.req_headers = handleParamsValue(
|
||||
data.req_headers,
|
||||
result.req_headers
|
||||
);
|
||||
result.req_headers = handleParamsValue(data.req_headers, result.req_headers);
|
||||
result.res_body_type = data.res_body_type;
|
||||
result.req_body_form = handleParamsValue(
|
||||
data.req_body_form,
|
||||
result.req_body_form
|
||||
);
|
||||
result.req_body_form = handleParamsValue(data.req_body_form, result.req_body_form);
|
||||
result.req_query = handleParamsValue(data.req_query, result.req_query);
|
||||
result.req_params = handleParamsValue(data.req_params, result.req_params);
|
||||
resultList[index] = result;
|
||||
@ -526,30 +491,30 @@ exports.getCaseList = async function getCaseList(id) {
|
||||
|
||||
function convertString(variable) {
|
||||
if (variable instanceof Error) {
|
||||
return variable.name + ": " + variable.message;
|
||||
return variable.name + ': ' + variable.message;
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(variable, null, " ");
|
||||
return JSON.stringify(variable, null, ' ');
|
||||
} catch (err) {
|
||||
return variable || "";
|
||||
return variable || '';
|
||||
}
|
||||
}
|
||||
|
||||
exports.runCaseScript = async function runCaseScript(params) {
|
||||
let script = params.script;
|
||||
if (!script) {
|
||||
return yapi.commons.resReturn("ok");
|
||||
return yapi.commons.resReturn('ok');
|
||||
}
|
||||
const logs = [];
|
||||
const context = {
|
||||
assert: require("assert"),
|
||||
assert: require('assert'),
|
||||
status: params.response.status,
|
||||
body: params.response.body,
|
||||
header: params.response.header,
|
||||
records: params.records,
|
||||
params: params.params,
|
||||
log: msg => {
|
||||
logs.push("log: " + convertString(msg));
|
||||
logs.push('log: ' + convertString(msg));
|
||||
}
|
||||
};
|
||||
|
||||
@ -561,6 +526,6 @@ exports.runCaseScript = async function runCaseScript(params) {
|
||||
} catch (err) {
|
||||
logs.push(convertString(err));
|
||||
result.logs = logs;
|
||||
return yapi.commons.resReturn(result, 400, err.name + ": " + err.message);
|
||||
return yapi.commons.resReturn(result, 400, err.name + ': ' + err.message);
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user