fork from bc4552c5a8
This commit is contained in:
422
server/controllers/open.js
Normal file
422
server/controllers/open.js
Normal file
@@ -0,0 +1,422 @@
|
||||
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 followModel = require('../models/follow.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, ArrayToObject } = require('../../common/utils.js');
|
||||
const renderToHtml = require('../utils/reportHtml');
|
||||
const HanldeImportData = require('../../common/HandleImportData');
|
||||
const _ = require('underscore');
|
||||
const createContex = require('../../common/createContext')
|
||||
|
||||
/**
|
||||
* {
|
||||
* postman: require('./m')
|
||||
* }
|
||||
*/
|
||||
const 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);
|
||||
this.followModel = yapi.getInst(followModel);
|
||||
this.userModel = yapi.getInst(userModel);
|
||||
this.handleValue = this.handleValue.bind(this);
|
||||
this.schemaMap = {
|
||||
runAutoTest: {
|
||||
'*id': 'number',
|
||||
project_id: 'string',
|
||||
token: 'string',
|
||||
mode: {
|
||||
type: 'string',
|
||||
default: 'html'
|
||||
},
|
||||
email: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
download: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
closeRemoveAdditional: true
|
||||
},
|
||||
importData: {
|
||||
'*type': 'string',
|
||||
url: 'string',
|
||||
'*token': 'string',
|
||||
json: 'string',
|
||||
project_id: 'string',
|
||||
merge: {
|
||||
type: 'string',
|
||||
default: 'normal'
|
||||
}
|
||||
}
|
||||
};
|
||||
yapi.emitHook('import_data', importDataModule);
|
||||
}
|
||||
|
||||
async importData(ctx) {
|
||||
let type = ctx.params.type;
|
||||
let content = ctx.params.json;
|
||||
let project_id = ctx.params.project_id;
|
||||
let dataSync = ctx.params.merge;
|
||||
|
||||
let warnMessage = ''
|
||||
|
||||
/**
|
||||
* 因为以前接口文档写错了,做下兼容
|
||||
*/
|
||||
try{
|
||||
if(!dataSync &&ctx.params.dataSync){
|
||||
warnMessage = 'importData Api 已废弃 dataSync 传参,请联系管理员将 dataSync 改为 merge.'
|
||||
dataSync = ctx.params.dataSync
|
||||
}
|
||||
}catch(e){}
|
||||
|
||||
let token = ctx.params.token;
|
||||
if (!type || !importDataModule[type]) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, '不存在的导入方式'));
|
||||
}
|
||||
|
||||
if (!content && !ctx.params.url) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, 'json 或者 url 参数,不能都为空'));
|
||||
}
|
||||
try {
|
||||
let request = require("request");// let Promise = require('Promise');
|
||||
let syncGet = function (url){
|
||||
return new Promise(function(resolve, reject){
|
||||
request.get({url : url}, function(error, response, body){
|
||||
if(error){
|
||||
reject(error);
|
||||
}else{
|
||||
resolve(body);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if(ctx.params.url){
|
||||
content = await syncGet(ctx.params.url);
|
||||
}else if(content.indexOf('http://') === 0 || content.indexOf('https://') === 0){
|
||||
content = await syncGet(content);
|
||||
}
|
||||
content = JSON.parse(content);
|
||||
} catch (e) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, 'json 格式有误:' + e));
|
||||
}
|
||||
|
||||
let menuList = await this.interfaceCatModel.list(project_id);
|
||||
/**
|
||||
* 防止分类被都被删除时取不到 selectCatid
|
||||
* 如果没有分类,增加一个默认分类
|
||||
*/
|
||||
if (menuList.length === 0) {
|
||||
const catInst = yapi.getInst(interfaceCatModel);
|
||||
const menu = await catInst.save({
|
||||
name: '默认分类',
|
||||
project_id: project_id,
|
||||
desc: '默认分类',
|
||||
uid: this.getUid(),
|
||||
add_time: yapi.commons.time(),
|
||||
up_time: yapi.commons.time()
|
||||
});
|
||||
menuList.push(menu);
|
||||
}
|
||||
let selectCatid = menuList[0]._id;
|
||||
let projectData = await this.projectModel.get(project_id);
|
||||
let res = await importDataModule[type](content);
|
||||
|
||||
let successMessage;
|
||||
let errorMessage = [];
|
||||
await HanldeImportData(
|
||||
res,
|
||||
project_id,
|
||||
selectCatid,
|
||||
menuList,
|
||||
projectData.basePath,
|
||||
dataSync,
|
||||
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')));
|
||||
}
|
||||
ctx.body = yapi.commons.resReturn(null, 0, successMessage + warnMessage);
|
||||
}
|
||||
|
||||
async projectInterfaceData(ctx) {
|
||||
ctx.body = 'projectInterfaceData';
|
||||
}
|
||||
|
||||
handleValue(val, global) {
|
||||
let globalValue = ArrayToObject(global);
|
||||
let context = Object.assign({}, {global: globalValue}, this.records);
|
||||
return handleParamsValue(val, context);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!this.$tokenAuth) {
|
||||
return (ctx.body = yapi.commons.resReturn(null, 40022, 'token 验证失败'));
|
||||
}
|
||||
// console.log(1231312)
|
||||
const token = ctx.query.token;
|
||||
|
||||
const projectId = ctx.params.project_id;
|
||||
const startTime = new Date().getTime();
|
||||
const records = (this.records = {});
|
||||
const reports = (this.reports = {});
|
||||
const testList = [];
|
||||
let id = ctx.params.id;
|
||||
let curEnvList = this.handleEvnParams(ctx.params);
|
||||
|
||||
let colData = await this.interfaceColModel.get(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;
|
||||
}
|
||||
caseList = caseList.data;
|
||||
for (let i = 0, l = caseList.length; i < l; i++) {
|
||||
let item = caseList[i];
|
||||
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 = 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;
|
||||
let result;
|
||||
// console.log('item',item.case_env)
|
||||
try {
|
||||
result = await this.handleTest(item);
|
||||
} catch (err) {
|
||||
result = err;
|
||||
}
|
||||
|
||||
reports[item.id] = result;
|
||||
records[item.id] = {
|
||||
params: result.params,
|
||||
body: result.res_body
|
||||
};
|
||||
testList.push(result);
|
||||
}
|
||||
|
||||
function getMessage(testList) {
|
||||
let successNum = 0,
|
||||
failedNum = 0,
|
||||
len = 0,
|
||||
msg = '';
|
||||
testList.forEach(item => {
|
||||
len++;
|
||||
if (item.code === 0) {
|
||||
successNum++;
|
||||
}
|
||||
else {
|
||||
failedNum++;
|
||||
}
|
||||
});
|
||||
if (failedNum === 0) {
|
||||
msg = `一共 ${len} 测试用例,全部验证通过`;
|
||||
} else {
|
||||
msg = `一共 ${len} 测试用例,${successNum} 个验证通过, ${failedNum} 个未通过。`;
|
||||
}
|
||||
|
||||
return { msg, len, successNum, failedNum };
|
||||
}
|
||||
|
||||
const endTime = new Date().getTime();
|
||||
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 = `${
|
||||
ctx.request.origin
|
||||
}/api/open/run_auto_test?id=${id}&token=${token}&mode=${ctx.params.mode}`;
|
||||
yapi.commons.sendNotice(projectId, {
|
||||
title: `YApi自动化测试报告`,
|
||||
content: `
|
||||
<html>
|
||||
<head>
|
||||
<title>测试报告</title>
|
||||
<meta charset="utf-8" />
|
||||
<body>
|
||||
<div>
|
||||
<h3>测试结果:</h3>
|
||||
<p>${reportsResult.message.msg}</p>
|
||||
<h3>测试结果详情如下:</h3>
|
||||
<p>${autoTestUrl}</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
||||
});
|
||||
}
|
||||
let mode = ctx.params.mode || 'html';
|
||||
if(ctx.params.download === true) {
|
||||
ctx.set('Content-Disposition', `attachment; filename=test.${mode}`);
|
||||
}
|
||||
if (ctx.params.mode === 'json') {
|
||||
return (ctx.body = reportsResult);
|
||||
} else {
|
||||
return (ctx.body = renderToHtml(reportsResult));
|
||||
}
|
||||
}
|
||||
|
||||
async handleTest(interfaceData) {
|
||||
let requestParams = {};
|
||||
let options;
|
||||
options = handleParams(interfaceData, this.handleValue, requestParams);
|
||||
let result = {
|
||||
id: interfaceData.id,
|
||||
name: interfaceData.casename,
|
||||
path: interfaceData.path,
|
||||
code: 400,
|
||||
validRes: []
|
||||
};
|
||||
try {
|
||||
options.taskId = this.getUid();
|
||||
let data = await crossRequest(options, interfaceData.pre_script, interfaceData.after_script,createContex(
|
||||
this.getUid(),
|
||||
interfaceData.project_id,
|
||||
interfaceData.interface_id
|
||||
));
|
||||
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);
|
||||
}
|
||||
|
||||
let validRes = [];
|
||||
|
||||
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;
|
||||
if (validRes.length === 0) {
|
||||
result.code = 0;
|
||||
result.validRes = [{ message: '验证通过' }];
|
||||
} else if (validRes.length > 0) {
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async handleScriptTest(interfaceData, response, validRes, requestParams) {
|
||||
|
||||
try {
|
||||
let test = await yapi.commons.runCaseScript({
|
||||
response: response,
|
||||
records: this.records,
|
||||
script: interfaceData.test_script,
|
||||
params: requestParams
|
||||
}, interfaceData.col_id, interfaceData.interface_id, this.getUid());
|
||||
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) {
|
||||
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 = req_header.filter(item => {
|
||||
return item && typeof item === 'object';
|
||||
});
|
||||
return req_header;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = openController;
|
||||
Reference in New Issue
Block a user