@codertqy/elpis 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.eslintrc +55 -0
- package/README.md +218 -0
- package/app/controller/base.js +40 -0
- package/app/controller/project.js +81 -0
- package/app/controller/view.js +22 -0
- package/app/extend/logger.js +43 -0
- package/app/middleware/api-params-verify.js +73 -0
- package/app/middleware/api-sign-verify.js +49 -0
- package/app/middleware/error-handler.js +31 -0
- package/app/middleware/project-handler.js +26 -0
- package/app/middleware.js +44 -0
- package/app/pages/assets/custom.css +14 -0
- package/app/pages/boot.js +56 -0
- package/app/pages/common/curl.js +84 -0
- package/app/pages/common/index.css +3 -0
- package/app/pages/common/utils.js +1 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +19 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +126 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +45 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +35 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +120 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +87 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +100 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +122 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +161 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +95 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +19 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +135 -0
- package/app/pages/dashboard/dashboard.vue +86 -0
- package/app/pages/dashboard/entry.dashboard.js +48 -0
- package/app/pages/store/index.js +3 -0
- package/app/pages/store/menu.js +68 -0
- package/app/pages/store/project.js +12 -0
- package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +107 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +138 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +140 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +122 -0
- package/app/pages/widgets/schema-form/form-item-config.js +20 -0
- package/app/pages/widgets/schema-form/schema-form.vue +135 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +51 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +63 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +41 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +49 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +126 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +22 -0
- package/app/pages/widgets/schema-table/schema-table.vue +259 -0
- package/app/pages/widgets/sider-container/sider-container.vue +27 -0
- package/app/public/output/entry.page1.tpl +40 -0
- package/app/public/output/entry.page2.tpl +11 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +239 -0
- package/app/router/project.js +22 -0
- package/app/router/view.js +17 -0
- package/app/router-schema/project.js +34 -0
- package/app/service/base.js +15 -0
- package/app/service/project.js +59 -0
- package/app/view/entry.tpl +25 -0
- package/app/webpack/config/webpack.base.js +280 -0
- package/app/webpack/config/webpack.dev.js +57 -0
- package/app/webpack/config/webpack.prod.js +127 -0
- package/app/webpack/dev.js +63 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/prod.js +22 -0
- package/config/config.beta.js +1 -0
- package/config/config.default.js +3 -0
- package/config/config.prod.js +1 -0
- package/elpis-core/env.js +27 -0
- package/elpis-core/index.js +98 -0
- package/elpis-core/loader/config.js +58 -0
- package/elpis-core/loader/controller.js +93 -0
- package/elpis-core/loader/extend.js +63 -0
- package/elpis-core/loader/middleware.js +84 -0
- package/elpis-core/loader/router-schema.js +56 -0
- package/elpis-core/loader/router.js +50 -0
- package/elpis-core/loader/service.js +85 -0
- package/index.js +38 -0
- package/model/index.js +129 -0
- package/package.json +92 -0
- package/test/controller/project.test.js +214 -0
package/model/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
const glob = require("glob");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { sep } = path;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 项目 project 继承 model 方法
|
|
8
|
+
* @param {} model 基类的数据
|
|
9
|
+
* @param {*} project 每一个项目类的数据
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
const porjectExtendModel = (model, project) => {
|
|
13
|
+
// 回调函数的参数是与前者对应
|
|
14
|
+
return _.mergeWith({}, model, project, (modelValue, projValue) => {
|
|
15
|
+
// 处理数组数据合并的特殊情况,不是数组,使用lodash默认合并
|
|
16
|
+
// 一般对应着 结构中的 menu 属性
|
|
17
|
+
if (_.isArray(modelValue) && _.isArray(projValue)) {
|
|
18
|
+
let result = [];
|
|
19
|
+
// 因为 project 继承 model 所以需要处理修改和新增内容的情况
|
|
20
|
+
// project有的,model也有 ---》修改(重载)
|
|
21
|
+
// project有的,model没有 ---》新增(扩展)
|
|
22
|
+
// model有的,project也有 ---》保留(继承)
|
|
23
|
+
|
|
24
|
+
// 处理 修改/保留 判断项目类中的是否有基类的。有就进行覆盖修改/保留
|
|
25
|
+
for (let i = 0; i < modelValue.length; i++) {
|
|
26
|
+
let modelItem = modelValue[i];
|
|
27
|
+
const projItem = projValue.find(
|
|
28
|
+
(projItem) => projItem.key === modelItem.key,
|
|
29
|
+
);
|
|
30
|
+
// 都有,则递归调用 porjectExtendModel 方法 覆盖修改
|
|
31
|
+
result.push(
|
|
32
|
+
projItem ? porjectExtendModel(modelItem, projItem) : modelItem,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
// 处理新增,判断基类中是否有项目类中的,没有则直接新增、有则不做任何操作
|
|
36
|
+
for (let i = 0; i < projValue.length; i++) {
|
|
37
|
+
let projItem = projValue[i];
|
|
38
|
+
const modelItem = modelValue.find(
|
|
39
|
+
(modelItem) => projItem.key === modelItem.key,
|
|
40
|
+
);
|
|
41
|
+
// 找不到直接新增
|
|
42
|
+
if (!modelItem) {
|
|
43
|
+
result.push(projItem);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// 拿到合并后的效果
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 解析 model 配置,并返回组织且继承后的数据结构
|
|
55
|
+
* [{
|
|
56
|
+
* modelKey: ${model},
|
|
57
|
+
* project:{
|
|
58
|
+
* proj1Key:${proj1},
|
|
59
|
+
* proj2Key:${proj2},
|
|
60
|
+
* }
|
|
61
|
+
* },...]
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
module.exports = (app) => {
|
|
65
|
+
const modelList = [];
|
|
66
|
+
// 遍历当前文件夹,构造模型数据结构,挂载到 modelList 上
|
|
67
|
+
const modelPath = path.resolve(process.cwd(), `.${sep}model`);
|
|
68
|
+
const fileList = glob.sync(path.resolve(modelPath, `.${sep}**${sep}**.js`));
|
|
69
|
+
|
|
70
|
+
// 遍历每一个文件
|
|
71
|
+
fileList.forEach((file) => {
|
|
72
|
+
if (file.indexOf("index.js") > -1) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// 区分配置类型是 (model / project)
|
|
76
|
+
|
|
77
|
+
// 具体的模型文件
|
|
78
|
+
const type = file.indexOf(`/project/`) > -1 ? "project" : "model";
|
|
79
|
+
if (type === "project") {
|
|
80
|
+
// 拿到基类key
|
|
81
|
+
const modelKey = file.match(/\/model\/(.*?)\/project/)?.[1];
|
|
82
|
+
// 具体的 项目类key
|
|
83
|
+
const projKey = file.match(/\/project\/(.*?)\.js/)?.[1];
|
|
84
|
+
|
|
85
|
+
const modelItem = modelList.find((item) => item.model?.key === modelKey);
|
|
86
|
+
if (!modelItem) {
|
|
87
|
+
// 初始化 model 数据结构
|
|
88
|
+
modelItem = {};
|
|
89
|
+
modelList.push(modelItem);
|
|
90
|
+
}
|
|
91
|
+
if (!modelItem.project) {
|
|
92
|
+
// 初始化 project 数据结构
|
|
93
|
+
modelItem.project = {};
|
|
94
|
+
}
|
|
95
|
+
// 将项目类的属性与值全部挂载到project上(以projKey作为键),并且注入projKey
|
|
96
|
+
modelItem.project[projKey] = require(path.resolve(file));
|
|
97
|
+
modelItem.project[projKey].key = projKey;
|
|
98
|
+
modelItem.project[projKey].modelKey = modelKey; //注入 modelKey 告诉所属哪一个
|
|
99
|
+
}
|
|
100
|
+
// 基类模型,重新构造数据格式
|
|
101
|
+
if (type === "model") {
|
|
102
|
+
// 拿到当前基类的类型:buiness / course
|
|
103
|
+
const modelKey = file.match(/\/model\/(.*?)\/model\.js/)?.[1];
|
|
104
|
+
let modelItem = modelList.find((item) => item.model?.key === modelKey);
|
|
105
|
+
if (!modelItem) {
|
|
106
|
+
// 初始化 model 数据结构
|
|
107
|
+
modelItem = {};
|
|
108
|
+
modelList.push(modelItem);
|
|
109
|
+
}
|
|
110
|
+
// 将基类中的属性与值全部挂载到model上,并且注入modelKey
|
|
111
|
+
modelItem.model = require(path.resolve(file));
|
|
112
|
+
modelItem.model.key = modelKey;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 数据进一步整理 project ==> 继承 model
|
|
117
|
+
modelList.forEach((item) => {
|
|
118
|
+
// 解析基类的数据,以及项目类的数据
|
|
119
|
+
const { model, project } = item;
|
|
120
|
+
|
|
121
|
+
// 遍历项目类数据,继承基类数据
|
|
122
|
+
for (const key in project) {
|
|
123
|
+
// 拿到的key属性就是 taobao、pdd之类的
|
|
124
|
+
// 值是数组,则进行遍历操作,如果是基本类型,则直接进行lodash中的覆盖合并
|
|
125
|
+
project[key] = porjectExtendModel(model, project[key]);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return modelList;
|
|
129
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codertqy/elpis",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"lint": "eslint --quiet --ext js,vue .",
|
|
8
|
+
"test": "set _ENV=local && mocha ./test/**/*.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://git.code.tencent.com/codertqy/elpis.git"
|
|
13
|
+
},
|
|
14
|
+
"author": "codertqy",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@babel/core": "^7.24.0",
|
|
18
|
+
"@element-plus/icons-vue": "^2.3.2",
|
|
19
|
+
"ajv": "^6.10.2",
|
|
20
|
+
"axios": "^0.19.2",
|
|
21
|
+
"echarts": "^5.5.0",
|
|
22
|
+
"element-plus": "^2.3.7",
|
|
23
|
+
"generate-password": "^1.7.1",
|
|
24
|
+
"glob": "^7.1.4",
|
|
25
|
+
"jsonwebtoken": "^9.0.2",
|
|
26
|
+
"knex": "^0.19.0",
|
|
27
|
+
"koa": "2.7.0",
|
|
28
|
+
"koa-bodyparser": "^4.2.1",
|
|
29
|
+
"koa-nunjucks-2": "^3.0.2",
|
|
30
|
+
"koa-router": "^7.4.0",
|
|
31
|
+
"koa-static": "^5.0.0",
|
|
32
|
+
"koa-useragent": "2.0.0",
|
|
33
|
+
"koa2-cors": "^2.0.6",
|
|
34
|
+
"less": "^3.8.1",
|
|
35
|
+
"lodash": "^4.17.21",
|
|
36
|
+
"log4js": "^6.9.1",
|
|
37
|
+
"md5": "^2.2.1",
|
|
38
|
+
"moment": "^2.29.4",
|
|
39
|
+
"mysql": "^2.18.1",
|
|
40
|
+
"node-schedule": "^2.1.1",
|
|
41
|
+
"nodemon": "^1.19.2",
|
|
42
|
+
"path": "^0.12.7",
|
|
43
|
+
"pinia": "^2.1.6",
|
|
44
|
+
"superagent": "^8.1.2",
|
|
45
|
+
"vue": "^3.3.4",
|
|
46
|
+
"vue-json-viewer": "^3.0.4",
|
|
47
|
+
"vue-router": "^4.2.4",
|
|
48
|
+
"vuex": "^4.1.0",
|
|
49
|
+
"@babel/plugin-transform-runtime": "^7.1.0",
|
|
50
|
+
"@babel/preset-env": "^7.4.5",
|
|
51
|
+
"babel-loader": "^8.0.4",
|
|
52
|
+
"clean-webpack-plugin": "^0.1.19",
|
|
53
|
+
"consoler": "^0.2.0",
|
|
54
|
+
"cross-env": "^10.1.0",
|
|
55
|
+
"css-loader": "^0.23.1",
|
|
56
|
+
"css-minimizer-webpack-plugin": "^5.0.1",
|
|
57
|
+
"directory-named-webpack-plugin": "^4.0.1",
|
|
58
|
+
"express": "^4.18.2",
|
|
59
|
+
"file-loader": "^6.2.0",
|
|
60
|
+
"html-webpack-inject-attributes-plugin": "^1.0.1",
|
|
61
|
+
"html-webpack-plugin": "^5.5.3",
|
|
62
|
+
"less-loader": "^11.1.3",
|
|
63
|
+
"mini-css-extract-plugin": "^2.7.6",
|
|
64
|
+
"style-loader": "^0.14.1",
|
|
65
|
+
"terser-webpack-plugin": "^5.3.16",
|
|
66
|
+
"thread-loader": "^4.0.4",
|
|
67
|
+
"url-loader": "^4.1.1",
|
|
68
|
+
"vue-loader": "^17.2.2",
|
|
69
|
+
"vue-style-loader": "^4.1.2",
|
|
70
|
+
"webpack": "^5.88.1",
|
|
71
|
+
"webpack-dev-middleware": "^6.1.1",
|
|
72
|
+
"webpack-hot-middleware": "^2.25.4",
|
|
73
|
+
"webpack-merge": "^4.2.1"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"assert": "^2.0.0",
|
|
77
|
+
"babel-eslint": "^10.0.2",
|
|
78
|
+
"eslint": "^7.32.0",
|
|
79
|
+
"eslint-plugin-import": "^2.28.1",
|
|
80
|
+
"eslint-plugin-vue": "^9.17.0",
|
|
81
|
+
"ghooks": "~1.0.3",
|
|
82
|
+
"mocha": "^6.1.4",
|
|
83
|
+
"supertest": "^4.0.2",
|
|
84
|
+
"validate-commit-msg": "~2.14.0"
|
|
85
|
+
},
|
|
86
|
+
"config": {
|
|
87
|
+
"ghooks": {
|
|
88
|
+
"commit-msg": "validate-commit-msg",
|
|
89
|
+
"pre-commit": "npm run lint"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// 断言库
|
|
2
|
+
const assert = require("assert");
|
|
3
|
+
// 单元测试 模拟请求测试的服务
|
|
4
|
+
const supertest = require("supertest");
|
|
5
|
+
const md5 = require("md5");
|
|
6
|
+
const elpisCore = require("../../elpis-core/index");
|
|
7
|
+
|
|
8
|
+
const signKey = "bgkjibal2kbhkc4vbakjl3sdvhja";
|
|
9
|
+
const st = Date.now();
|
|
10
|
+
|
|
11
|
+
describe("测试 project 相关接口", function () {
|
|
12
|
+
this.timeout(60000);
|
|
13
|
+
|
|
14
|
+
let modelList;
|
|
15
|
+
const projectList = [];
|
|
16
|
+
let request;
|
|
17
|
+
it("启动服务", async () => {
|
|
18
|
+
const app = await elpisCore.start();
|
|
19
|
+
|
|
20
|
+
// 进行对比的数据
|
|
21
|
+
modelList = require("../../model/index")(app);
|
|
22
|
+
modelList.forEach((modelItem) => {
|
|
23
|
+
const { project } = modelItem;
|
|
24
|
+
for (const projKey in project) {
|
|
25
|
+
// 将pdd,taobao这种添加到projectList
|
|
26
|
+
projectList.push(project[projKey]);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
request = supertest(app.listen());
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// 测试 /api/project 接口
|
|
34
|
+
it("GET /api/project without proj_key", async () => {
|
|
35
|
+
let tmpRequest = request.get("/api/project");
|
|
36
|
+
tmpRequest = tmpRequest.set("s_sign", md5(`${signKey}_${st}`));
|
|
37
|
+
tmpRequest = tmpRequest.set("s_t", st);
|
|
38
|
+
const res = await tmpRequest;
|
|
39
|
+
assert(res.body.success === false);
|
|
40
|
+
|
|
41
|
+
const resBody = res.body;
|
|
42
|
+
assert(resBody.code === 442);
|
|
43
|
+
assert(resBody.message.indexOf("request validate fail") > -1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("GET /api/project fail", async () => {
|
|
47
|
+
let tmpRequest = request.get("/api/project");
|
|
48
|
+
tmpRequest = tmpRequest.set("s_sign", md5(`${signKey}_${st}`));
|
|
49
|
+
tmpRequest = tmpRequest.set("s_t", st);
|
|
50
|
+
tmpRequest = tmpRequest.query({
|
|
51
|
+
proj_key: "xxxxxxxxxxxxxxx",
|
|
52
|
+
});
|
|
53
|
+
const res = await tmpRequest;
|
|
54
|
+
console.log(res.body);
|
|
55
|
+
assert(res.body.success === false);
|
|
56
|
+
const resBody = res.body;
|
|
57
|
+
assert(resBody.code === 50000);
|
|
58
|
+
assert(resBody.message.indexOf("项目异常") > -1);
|
|
59
|
+
});
|
|
60
|
+
it("GET /api/project with proj_key", async () => {
|
|
61
|
+
// 校验 menu 菜单
|
|
62
|
+
const checkMenuItem = (menuItem) => {
|
|
63
|
+
console.log(`--------- GET /api/project with proj_key - menuKey: ${projKey}`);
|
|
64
|
+
assert(menuItem.key);
|
|
65
|
+
assert(menuItem.name);
|
|
66
|
+
assert(menuItem.menuType);
|
|
67
|
+
|
|
68
|
+
if (menuItem.menuType === "group") {
|
|
69
|
+
assert(menuItem.subMenu !== undefined);
|
|
70
|
+
menuItem.subMenu.forEach((subMenuItem) => {
|
|
71
|
+
// 递归调用 subMenu 里面的每一项 都是使用 checkMenuItem 方法
|
|
72
|
+
checkMenuItem(subMenuItem);
|
|
73
|
+
});
|
|
74
|
+
} else if (menuItem.menuType === "module") {
|
|
75
|
+
checkModule(menuItem);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// 校验 module 菜单配置
|
|
80
|
+
const checkModule = (menuItem) => {
|
|
81
|
+
const { moduleType } = menuItem;
|
|
82
|
+
assert(moduleType);
|
|
83
|
+
if (moduleType === "sider") {
|
|
84
|
+
const { siderConfig } = menuItem;
|
|
85
|
+
assert(siderConfig);
|
|
86
|
+
assert(siderConfig.menu);
|
|
87
|
+
siderConfig.menu.forEach((siderMenuItem) => {
|
|
88
|
+
// 递归调用 menu 里面的每一项 都是使用 checkMenuItem 方法
|
|
89
|
+
checkMenuItem(siderMenuItem);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (moduleType === "iframe") {
|
|
93
|
+
const { iframeConfig } = menuItem;
|
|
94
|
+
assert(iframeConfig);
|
|
95
|
+
assert(iframeConfig.path !== undefined);
|
|
96
|
+
}
|
|
97
|
+
if (moduleType === "custom") {
|
|
98
|
+
const { customConfig } = menuItem;
|
|
99
|
+
assert(customConfig);
|
|
100
|
+
assert(customConfig.path !== undefined);
|
|
101
|
+
}
|
|
102
|
+
if (moduleType === "schema") {
|
|
103
|
+
const { schemaConfig } = menuItem;
|
|
104
|
+
assert(schemaConfig);
|
|
105
|
+
assert(schemaConfig.api !== undefined);
|
|
106
|
+
assert(schemaConfig.schema);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// 循环获取 projKey 验证每一个
|
|
110
|
+
for (let i = 0; i < projectList.length; i++) {
|
|
111
|
+
const { key: projKey } = projectList[i];
|
|
112
|
+
console.log(`GET /api/project with proj_key: ${projKey}`);
|
|
113
|
+
let tmpRequest = request.get("/api/project");
|
|
114
|
+
tmpRequest = tmpRequest.set("s_sign", md5(`${signKey}_${st}`));
|
|
115
|
+
tmpRequest = tmpRequest.set("s_t", st);
|
|
116
|
+
tmpRequest = tmpRequest.query({
|
|
117
|
+
proj_key: projKey,
|
|
118
|
+
});
|
|
119
|
+
const res = await tmpRequest;
|
|
120
|
+
assert(res.body.success === true);
|
|
121
|
+
|
|
122
|
+
const resData = res.body.data;
|
|
123
|
+
assert(resData.key === projKey);
|
|
124
|
+
assert(resData.name);
|
|
125
|
+
assert(resData.modelKey);
|
|
126
|
+
assert(resData.desc !== undefined);
|
|
127
|
+
assert(resData.homePage !== undefined);
|
|
128
|
+
|
|
129
|
+
const { menu } = resData;
|
|
130
|
+
menu.forEach((menuItem) => {
|
|
131
|
+
checkMenuItem(menuItem);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// 测试 /api/project/list 接口
|
|
137
|
+
it("GET /api/project/list without proj_key", async () => {
|
|
138
|
+
let tmpRequest = request.get("/api/project/list");
|
|
139
|
+
tmpRequest = tmpRequest.set("s_sign", md5(`${signKey}_${st}`));
|
|
140
|
+
tmpRequest = tmpRequest.set("s_t", st);
|
|
141
|
+
const res = await tmpRequest;
|
|
142
|
+
// 针对数据进行断言
|
|
143
|
+
assert(res.body.success === true);
|
|
144
|
+
|
|
145
|
+
const resData = res.body.data;
|
|
146
|
+
assert(resData.length === projectList.length);
|
|
147
|
+
for (let i = 0; i < resData.length; i++) {
|
|
148
|
+
const item = resData[i];
|
|
149
|
+
assert(item.key);
|
|
150
|
+
assert(item.name);
|
|
151
|
+
assert(item.desc !== undefined);
|
|
152
|
+
assert(item.modelKey);
|
|
153
|
+
assert(item.homePage !== undefined);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("GET /api/project/list with proj_key", async () => {
|
|
158
|
+
// 取出project对象中的每一个对象中的唯一的key属性
|
|
159
|
+
const { key: projKey } =
|
|
160
|
+
projectList[Math.floor(Math.random() * projectList.length)];
|
|
161
|
+
// 查找当前的 projKey 所属已存在的那一个里面
|
|
162
|
+
const { modelKey } = projectList.find((item) => item.key === projKey);
|
|
163
|
+
let tmpRequest = request.get("/api/project/list");
|
|
164
|
+
tmpRequest = tmpRequest.set("s_sign", md5(`${signKey}_${st}`));
|
|
165
|
+
tmpRequest = tmpRequest.set("s_t", st);
|
|
166
|
+
// 携带请求参数
|
|
167
|
+
tmpRequest = tmpRequest.query({
|
|
168
|
+
proj_key: projKey,
|
|
169
|
+
});
|
|
170
|
+
const res = await tmpRequest;
|
|
171
|
+
assert(res.body.success === true);
|
|
172
|
+
|
|
173
|
+
const resData = res.body.data;
|
|
174
|
+
assert(
|
|
175
|
+
projectList.filter(
|
|
176
|
+
(item) => (item.modelKey === modelKey.length) === resData.length,
|
|
177
|
+
),
|
|
178
|
+
);
|
|
179
|
+
for (let i = 0; i < resData.length; i++) {
|
|
180
|
+
const item = resData[i];
|
|
181
|
+
assert(item.key);
|
|
182
|
+
assert(item.name);
|
|
183
|
+
assert(item.desc !== undefined);
|
|
184
|
+
assert(item.modelKey);
|
|
185
|
+
assert(item.homePage !== undefined);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// 测试 /api/project/model_list 接口
|
|
190
|
+
it("GET /api/project/model_list", async () => {
|
|
191
|
+
let tmpRequest = request.get("/api/project/model_list");
|
|
192
|
+
tmpRequest = tmpRequest.set("s_sign", md5(`${signKey}_${st}`));
|
|
193
|
+
tmpRequest = tmpRequest.set("s_t", st);
|
|
194
|
+
const res = await tmpRequest;
|
|
195
|
+
|
|
196
|
+
// 针对数据进行断言
|
|
197
|
+
assert(res.body.success === true);
|
|
198
|
+
|
|
199
|
+
const resData = res.body.data;
|
|
200
|
+
assert(resData.length > 0);
|
|
201
|
+
|
|
202
|
+
for (let i = 0; i < resData.length; i++) {
|
|
203
|
+
const item = resData[i];
|
|
204
|
+
assert(item.model);
|
|
205
|
+
assert(item.model.key);
|
|
206
|
+
assert(item.model.name);
|
|
207
|
+
assert(item.project);
|
|
208
|
+
for (const projKey in item.project) {
|
|
209
|
+
assert(item.project[projKey].key);
|
|
210
|
+
assert(item.project[projKey].name);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|