@adaptivestone/framework 4.5.0 → 4.6.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/CHANGELOG.md +4 -0
- package/controllers/Auth.test.js +2 -0
- package/controllers/Home.test.js +2 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +3433 -0
- package/coverage/coverage-final.json +41 -0
- package/coverage/favicon.png +0 -0
- package/coverage/framework/config/auth.js.html +100 -0
- package/coverage/framework/config/http.js.html +112 -0
- package/coverage/framework/config/i18n.js.html +121 -0
- package/coverage/framework/config/index.html +236 -0
- package/coverage/framework/config/log.js.html +151 -0
- package/coverage/framework/config/mail.js.html +172 -0
- package/coverage/framework/config/mongo.js.html +94 -0
- package/coverage/framework/config/rateLimiter.js.html +133 -0
- package/coverage/framework/config/redis.js.html +97 -0
- package/coverage/framework/config/validate.js.html +94 -0
- package/coverage/framework/controllers/Auth.js.html +721 -0
- package/coverage/framework/controllers/Home.js.html +169 -0
- package/coverage/framework/controllers/index.html +146 -0
- package/coverage/framework/controllers/index.js.html +268 -0
- package/coverage/framework/controllers/test/SomeController.js.html +616 -0
- package/coverage/framework/controllers/test/index.html +116 -0
- package/coverage/framework/helpers/redis/clearNamespace.js.html +127 -0
- package/coverage/framework/helpers/redis/index.html +116 -0
- package/coverage/framework/index.html +116 -0
- package/coverage/framework/models/Sequence.js.html +151 -0
- package/coverage/framework/models/User.js.html +859 -0
- package/coverage/framework/models/index.html +131 -0
- package/coverage/framework/modules/AbstractController.js.html +1315 -0
- package/coverage/framework/modules/AbstractModel.js.html +268 -0
- package/coverage/framework/modules/Base.js.html +577 -0
- package/coverage/framework/modules/index.html +146 -0
- package/coverage/framework/server.js.html +820 -0
- package/coverage/framework/services/cache/Cache.js.html +430 -0
- package/coverage/framework/services/cache/index.html +116 -0
- package/coverage/framework/services/documentation/DocumentationGenerator.js.html +598 -0
- package/coverage/framework/services/documentation/index.html +116 -0
- package/coverage/framework/services/http/HttpServer.js.html +373 -0
- package/coverage/framework/services/http/index.html +116 -0
- package/coverage/framework/services/http/middleware/AbstractMiddleware.js.html +238 -0
- package/coverage/framework/services/http/middleware/Auth.js.html +145 -0
- package/coverage/framework/services/http/middleware/GetUserByToken.js.html +223 -0
- package/coverage/framework/services/http/middleware/I18n.js.html +442 -0
- package/coverage/framework/services/http/middleware/Pagination.js.html +253 -0
- package/coverage/framework/services/http/middleware/PrepareAppInfo.js.html +139 -0
- package/coverage/framework/services/http/middleware/RateLimiter.js.html +472 -0
- package/coverage/framework/services/http/middleware/RequestLogger.js.html +151 -0
- package/coverage/framework/services/http/middleware/RequestParser.js.html +199 -0
- package/coverage/framework/services/http/middleware/Role.js.html +172 -0
- package/coverage/framework/services/http/middleware/index.html +251 -0
- package/coverage/framework/services/http/middleware/test/CheckFlag.js.html +139 -0
- package/coverage/framework/services/http/middleware/test/index.html +116 -0
- package/coverage/framework/services/messaging/email/index.html +116 -0
- package/coverage/framework/services/messaging/email/index.js.html +739 -0
- package/coverage/framework/services/messaging/index.html +116 -0
- package/coverage/framework/services/messaging/index.js.html +100 -0
- package/coverage/framework/services/validate/ValidateService.js.html +568 -0
- package/coverage/framework/services/validate/drivers/AbstractValidator.js.html +196 -0
- package/coverage/framework/services/validate/drivers/CustomValidator.js.html +241 -0
- package/coverage/framework/services/validate/drivers/YupValidator.js.html +394 -0
- package/coverage/framework/services/validate/drivers/index.html +146 -0
- package/coverage/framework/services/validate/index.html +116 -0
- package/coverage/index.html +341 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/models/Sequence.test.js +2 -0
- package/models/User.test.js +2 -0
- package/modules/Modules.test.js +3 -2
- package/package.json +6 -18
- package/services/http/middleware/I18n.test.js +12 -5
- package/services/http/middleware/PrepareAppInfo.test.js +7 -3
- package/services/http/middleware/RateLimiter.test.js +10 -6
- package/services/http/middleware/RequestParser.test.js +7 -4
- package/services/validate/ValidateService.test.js +2 -0
- package/tests/setup.js +1 -1
- package/tests/setupVitest.js +119 -0
- package/vitest.config.js +9 -0
- package/babel.config.js +0 -3
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
var addSorting = (function() {
|
|
3
|
+
'use strict';
|
|
4
|
+
var cols,
|
|
5
|
+
currentSort = {
|
|
6
|
+
index: 0,
|
|
7
|
+
desc: false
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// returns the summary table element
|
|
11
|
+
function getTable() {
|
|
12
|
+
return document.querySelector('.coverage-summary');
|
|
13
|
+
}
|
|
14
|
+
// returns the thead element of the summary table
|
|
15
|
+
function getTableHeader() {
|
|
16
|
+
return getTable().querySelector('thead tr');
|
|
17
|
+
}
|
|
18
|
+
// returns the tbody element of the summary table
|
|
19
|
+
function getTableBody() {
|
|
20
|
+
return getTable().querySelector('tbody');
|
|
21
|
+
}
|
|
22
|
+
// returns the th element for nth column
|
|
23
|
+
function getNthColumn(n) {
|
|
24
|
+
return getTableHeader().querySelectorAll('th')[n];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function onFilterInput() {
|
|
28
|
+
const searchValue = document.getElementById('fileSearch').value;
|
|
29
|
+
const rows = document.getElementsByTagName('tbody')[0].children;
|
|
30
|
+
for (let i = 0; i < rows.length; i++) {
|
|
31
|
+
const row = rows[i];
|
|
32
|
+
if (
|
|
33
|
+
row.textContent
|
|
34
|
+
.toLowerCase()
|
|
35
|
+
.includes(searchValue.toLowerCase())
|
|
36
|
+
) {
|
|
37
|
+
row.style.display = '';
|
|
38
|
+
} else {
|
|
39
|
+
row.style.display = 'none';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// loads the search box
|
|
45
|
+
function addSearchBox() {
|
|
46
|
+
var template = document.getElementById('filterTemplate');
|
|
47
|
+
var templateClone = template.content.cloneNode(true);
|
|
48
|
+
templateClone.getElementById('fileSearch').oninput = onFilterInput;
|
|
49
|
+
template.parentElement.appendChild(templateClone);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// loads all columns
|
|
53
|
+
function loadColumns() {
|
|
54
|
+
var colNodes = getTableHeader().querySelectorAll('th'),
|
|
55
|
+
colNode,
|
|
56
|
+
cols = [],
|
|
57
|
+
col,
|
|
58
|
+
i;
|
|
59
|
+
|
|
60
|
+
for (i = 0; i < colNodes.length; i += 1) {
|
|
61
|
+
colNode = colNodes[i];
|
|
62
|
+
col = {
|
|
63
|
+
key: colNode.getAttribute('data-col'),
|
|
64
|
+
sortable: !colNode.getAttribute('data-nosort'),
|
|
65
|
+
type: colNode.getAttribute('data-type') || 'string'
|
|
66
|
+
};
|
|
67
|
+
cols.push(col);
|
|
68
|
+
if (col.sortable) {
|
|
69
|
+
col.defaultDescSort = col.type === 'number';
|
|
70
|
+
colNode.innerHTML =
|
|
71
|
+
colNode.innerHTML + '<span class="sorter"></span>';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return cols;
|
|
75
|
+
}
|
|
76
|
+
// attaches a data attribute to every tr element with an object
|
|
77
|
+
// of data values keyed by column name
|
|
78
|
+
function loadRowData(tableRow) {
|
|
79
|
+
var tableCols = tableRow.querySelectorAll('td'),
|
|
80
|
+
colNode,
|
|
81
|
+
col,
|
|
82
|
+
data = {},
|
|
83
|
+
i,
|
|
84
|
+
val;
|
|
85
|
+
for (i = 0; i < tableCols.length; i += 1) {
|
|
86
|
+
colNode = tableCols[i];
|
|
87
|
+
col = cols[i];
|
|
88
|
+
val = colNode.getAttribute('data-value');
|
|
89
|
+
if (col.type === 'number') {
|
|
90
|
+
val = Number(val);
|
|
91
|
+
}
|
|
92
|
+
data[col.key] = val;
|
|
93
|
+
}
|
|
94
|
+
return data;
|
|
95
|
+
}
|
|
96
|
+
// loads all row data
|
|
97
|
+
function loadData() {
|
|
98
|
+
var rows = getTableBody().querySelectorAll('tr'),
|
|
99
|
+
i;
|
|
100
|
+
|
|
101
|
+
for (i = 0; i < rows.length; i += 1) {
|
|
102
|
+
rows[i].data = loadRowData(rows[i]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// sorts the table using the data for the ith column
|
|
106
|
+
function sortByIndex(index, desc) {
|
|
107
|
+
var key = cols[index].key,
|
|
108
|
+
sorter = function(a, b) {
|
|
109
|
+
a = a.data[key];
|
|
110
|
+
b = b.data[key];
|
|
111
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
112
|
+
},
|
|
113
|
+
finalSorter = sorter,
|
|
114
|
+
tableBody = document.querySelector('.coverage-summary tbody'),
|
|
115
|
+
rowNodes = tableBody.querySelectorAll('tr'),
|
|
116
|
+
rows = [],
|
|
117
|
+
i;
|
|
118
|
+
|
|
119
|
+
if (desc) {
|
|
120
|
+
finalSorter = function(a, b) {
|
|
121
|
+
return -1 * sorter(a, b);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for (i = 0; i < rowNodes.length; i += 1) {
|
|
126
|
+
rows.push(rowNodes[i]);
|
|
127
|
+
tableBody.removeChild(rowNodes[i]);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
rows.sort(finalSorter);
|
|
131
|
+
|
|
132
|
+
for (i = 0; i < rows.length; i += 1) {
|
|
133
|
+
tableBody.appendChild(rows[i]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// removes sort indicators for current column being sorted
|
|
137
|
+
function removeSortIndicators() {
|
|
138
|
+
var col = getNthColumn(currentSort.index),
|
|
139
|
+
cls = col.className;
|
|
140
|
+
|
|
141
|
+
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
|
142
|
+
col.className = cls;
|
|
143
|
+
}
|
|
144
|
+
// adds sort indicators for current column being sorted
|
|
145
|
+
function addSortIndicators() {
|
|
146
|
+
getNthColumn(currentSort.index).className += currentSort.desc
|
|
147
|
+
? ' sorted-desc'
|
|
148
|
+
: ' sorted';
|
|
149
|
+
}
|
|
150
|
+
// adds event listeners for all sorter widgets
|
|
151
|
+
function enableUI() {
|
|
152
|
+
var i,
|
|
153
|
+
el,
|
|
154
|
+
ithSorter = function ithSorter(i) {
|
|
155
|
+
var col = cols[i];
|
|
156
|
+
|
|
157
|
+
return function() {
|
|
158
|
+
var desc = col.defaultDescSort;
|
|
159
|
+
|
|
160
|
+
if (currentSort.index === i) {
|
|
161
|
+
desc = !currentSort.desc;
|
|
162
|
+
}
|
|
163
|
+
sortByIndex(i, desc);
|
|
164
|
+
removeSortIndicators();
|
|
165
|
+
currentSort.index = i;
|
|
166
|
+
currentSort.desc = desc;
|
|
167
|
+
addSortIndicators();
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
for (i = 0; i < cols.length; i += 1) {
|
|
171
|
+
if (cols[i].sortable) {
|
|
172
|
+
// add the click event handler on the th so users
|
|
173
|
+
// dont have to click on those tiny arrows
|
|
174
|
+
el = getNthColumn(i).querySelector('.sorter').parentElement;
|
|
175
|
+
if (el.addEventListener) {
|
|
176
|
+
el.addEventListener('click', ithSorter(i));
|
|
177
|
+
} else {
|
|
178
|
+
el.attachEvent('onclick', ithSorter(i));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// adds sorting functionality to the UI
|
|
184
|
+
return function() {
|
|
185
|
+
if (!getTable()) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
cols = loadColumns();
|
|
189
|
+
loadData();
|
|
190
|
+
addSearchBox();
|
|
191
|
+
addSortIndicators();
|
|
192
|
+
enableUI();
|
|
193
|
+
};
|
|
194
|
+
})();
|
|
195
|
+
|
|
196
|
+
window.addEventListener('load', addSorting);
|
package/models/Sequence.test.js
CHANGED
package/models/User.test.js
CHANGED
package/modules/Modules.test.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import SomeController from '../controllers/test/SomeController';
|
|
3
|
+
import AbstractController from './AbstractController';
|
|
3
4
|
|
|
4
5
|
describe('abstract controller methods', () => {
|
|
5
6
|
it('can get routes', async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptivestone/framework",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "Adaptive stone node js framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"dev": "nodemon ./index.js",
|
|
16
16
|
"prod": "nodemon ./cluster.js",
|
|
17
|
-
"test": "
|
|
17
|
+
"test": "vitest run --coverage",
|
|
18
18
|
"prettier": "prettier --check '**/*.(js|jsx|ts|tsx|json|css|scss|md)'",
|
|
19
19
|
"lint": "eslint '**/*.js'",
|
|
20
20
|
"lint:fix": "eslint '**/*.js' --fix",
|
|
@@ -25,18 +25,6 @@
|
|
|
25
25
|
"benchmark2": "h2load -n 10000 -c 50 https://localhost:3300/",
|
|
26
26
|
"redis:docker": "docker run --rm -p 6379:6379 redis"
|
|
27
27
|
},
|
|
28
|
-
"jest": {
|
|
29
|
-
"setupFilesAfterEnv": [
|
|
30
|
-
"./tests/setup.js"
|
|
31
|
-
],
|
|
32
|
-
"testEnvironment": "node",
|
|
33
|
-
"verbose": true,
|
|
34
|
-
"collectCoverage": true,
|
|
35
|
-
"coverageReporters": [
|
|
36
|
-
"text",
|
|
37
|
-
"text-summary"
|
|
38
|
-
]
|
|
39
|
-
},
|
|
40
28
|
"author": "Andrey Logunov",
|
|
41
29
|
"license": "MIT",
|
|
42
30
|
"dependencies": {
|
|
@@ -63,17 +51,17 @@
|
|
|
63
51
|
"yup": "^1.0.0"
|
|
64
52
|
},
|
|
65
53
|
"devDependencies": {
|
|
66
|
-
"@
|
|
54
|
+
"@vitest/coverage-v8": "^0.34.3",
|
|
67
55
|
"eslint": "^8.0.0",
|
|
68
56
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
69
57
|
"eslint-config-prettier": "^9.0.0",
|
|
70
|
-
"eslint-plugin-
|
|
58
|
+
"eslint-plugin-vitest": "^0.3.1",
|
|
71
59
|
"husky": "^8.0.0",
|
|
72
|
-
"jest": "^29.0.0",
|
|
73
60
|
"lint-staged": "^14.0.0",
|
|
74
61
|
"mongodb-memory-server": "^8.0.2",
|
|
75
62
|
"nodemon": "^3.0.1",
|
|
76
|
-
"prettier": "^3.0.0"
|
|
63
|
+
"prettier": "^3.0.0",
|
|
64
|
+
"vitest": "^0.34.3"
|
|
77
65
|
},
|
|
78
66
|
"lint-staged": {
|
|
79
67
|
"**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { beforeAll, describe, it, expect } from 'vitest';
|
|
2
|
+
import I18n from './I18n';
|
|
2
3
|
|
|
3
4
|
describe('i18n middleware methods', () => {
|
|
4
5
|
let middleware;
|
|
@@ -45,13 +46,16 @@ describe('i18n middleware methods', () => {
|
|
|
45
46
|
|
|
46
47
|
it('middleware that works', async () => {
|
|
47
48
|
expect.assertions(4);
|
|
48
|
-
|
|
49
|
+
let isCalled = false;
|
|
50
|
+
const nextFunction = () => {
|
|
51
|
+
isCalled = true;
|
|
52
|
+
};
|
|
49
53
|
const req = {
|
|
50
54
|
get: () => 'en',
|
|
51
55
|
appInfo: {},
|
|
52
56
|
};
|
|
53
57
|
await middleware.middleware(req, {}, nextFunction);
|
|
54
|
-
expect(
|
|
58
|
+
expect(isCalled).toBe(true);
|
|
55
59
|
expect(req.appInfo.i18n).toBeDefined();
|
|
56
60
|
expect(req.appInfo.i18n.t('aaaaa')).toBe('aaaaa');
|
|
57
61
|
expect(req.i18n.t('aaaaa')).toBe('aaaaa'); // proxy test
|
|
@@ -62,13 +66,16 @@ describe('i18n middleware methods', () => {
|
|
|
62
66
|
global.server.app.updateConfig('i18n', { enabled: false });
|
|
63
67
|
middleware = new I18n(global.server.app);
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
let isCalled = false;
|
|
70
|
+
const nextFunction = () => {
|
|
71
|
+
isCalled = true;
|
|
72
|
+
};
|
|
66
73
|
const req = {
|
|
67
74
|
get: () => 'en',
|
|
68
75
|
appInfo: {},
|
|
69
76
|
};
|
|
70
77
|
await middleware.middleware(req, {}, nextFunction);
|
|
71
|
-
expect(
|
|
78
|
+
expect(isCalled).toBe(true);
|
|
72
79
|
expect(req.appInfo.i18n).toBeDefined();
|
|
73
80
|
expect(req.appInfo.i18n.t('aaaaa')).toBe('aaaaa');
|
|
74
81
|
expect(req.i18n.t('aaaaa')).toBe('aaaaa'); // proxy test
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import PrepareAppInfo from './PrepareAppInfo';
|
|
2
3
|
|
|
3
4
|
describe('prepareAppInfo methods', () => {
|
|
4
5
|
it('have description fields', async () => {
|
|
@@ -10,10 +11,13 @@ describe('prepareAppInfo methods', () => {
|
|
|
10
11
|
it('middleware that works', async () => {
|
|
11
12
|
expect.assertions(3);
|
|
12
13
|
const middleware = new PrepareAppInfo(global.server.app);
|
|
13
|
-
|
|
14
|
+
let isCalled = false;
|
|
15
|
+
const nextFunction = () => {
|
|
16
|
+
isCalled = true;
|
|
17
|
+
};
|
|
14
18
|
const req = {};
|
|
15
19
|
await middleware.middleware(req, {}, nextFunction);
|
|
16
|
-
expect(
|
|
20
|
+
expect(isCalled).toBe(true);
|
|
17
21
|
expect(req.appInfo).toBeDefined();
|
|
18
22
|
req.appInfo.test = 5;
|
|
19
23
|
await middleware.middleware(req, {}, nextFunction);
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { setTimeout } from 'node:timers/promises';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import { beforeAll, afterAll, describe, it, expect } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import RateLimiter from './RateLimiter';
|
|
3
6
|
|
|
4
7
|
let mongoRateLimiter;
|
|
5
8
|
|
|
6
9
|
describe('rate limiter methods', () => {
|
|
7
|
-
beforeAll(() => {
|
|
10
|
+
beforeAll(async () => {
|
|
11
|
+
await setTimeout(20);
|
|
12
|
+
|
|
8
13
|
mongoRateLimiter = new RateLimiter(global.server.app, {
|
|
9
14
|
driver: 'mongo',
|
|
10
15
|
limiterOptions: {
|
|
11
|
-
keyPrefix: `mongo_${Date.now()}`,
|
|
16
|
+
keyPrefix: `mongo_${Date.now()}_${crypto.randomUUID()}}`,
|
|
12
17
|
},
|
|
13
18
|
});
|
|
14
19
|
});
|
|
@@ -89,7 +94,6 @@ describe('rate limiter methods', () => {
|
|
|
89
94
|
const rateLimiter = new RateLimiter(global.server.app, {
|
|
90
95
|
driver: 'unknown',
|
|
91
96
|
});
|
|
92
|
-
const nextFunction = jest.fn(() => {});
|
|
93
97
|
const req = {
|
|
94
98
|
appInfo: {},
|
|
95
99
|
};
|
|
@@ -106,7 +110,7 @@ describe('rate limiter methods', () => {
|
|
|
106
110
|
isSend = true;
|
|
107
111
|
},
|
|
108
112
|
},
|
|
109
|
-
|
|
113
|
+
() => {},
|
|
110
114
|
);
|
|
111
115
|
expect(status).toBe(500);
|
|
112
116
|
expect(isSend).toBe(true);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import RequestParser from './RequestParser';
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
// TODO change on ESM
|
|
7
|
+
const formidable = require('formidable');
|
|
5
8
|
|
|
6
9
|
describe('reqest parser limiter methods', () => {
|
|
7
10
|
it('have description fields', async () => {
|
|
@@ -24,7 +27,7 @@ describe('reqest parser limiter methods', () => {
|
|
|
24
27
|
expect(req.body.multipleFiles).toBeDefined();
|
|
25
28
|
expect(
|
|
26
29
|
req.body.multipleFiles[0] instanceof formidable.PersistentFile,
|
|
27
|
-
).
|
|
30
|
+
).toBeTruthy();
|
|
28
31
|
|
|
29
32
|
res.writeHead(200);
|
|
30
33
|
res.end('ok');
|
package/tests/setup.js
CHANGED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { beforeAll, beforeEach, afterEach, afterAll } from 'vitest';
|
|
3
|
+
|
|
4
|
+
const { MongoMemoryReplSet } = require('mongodb-memory-server');
|
|
5
|
+
|
|
6
|
+
const mongoose = require('mongoose');
|
|
7
|
+
|
|
8
|
+
let mongoMemoryServerInstance;
|
|
9
|
+
|
|
10
|
+
const redis = require('redis');
|
|
11
|
+
const Server = require('../server');
|
|
12
|
+
|
|
13
|
+
const clearRedisNamespace = require('../helpers/redis/clearNamespace');
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
|
|
16
|
+
beforeAll(async () => {
|
|
17
|
+
mongoMemoryServerInstance = await MongoMemoryReplSet.create({
|
|
18
|
+
// binary: { version: '4.4.6' },
|
|
19
|
+
replSet: { count: 1, storageEngine: 'wiredTiger' },
|
|
20
|
+
});
|
|
21
|
+
await mongoMemoryServerInstance.waitUntilRunning();
|
|
22
|
+
process.env.LOGGER_CONSOLE_LEVEL = 'error';
|
|
23
|
+
const connectionStringMongo = await mongoMemoryServerInstance.getUri();
|
|
24
|
+
// console.info('MONGO_URI: ', connectionStringMongo);
|
|
25
|
+
global.server = new Server({
|
|
26
|
+
folders: {
|
|
27
|
+
config: process.env.TEST_FOLDER_CONFIG || path.resolve('./config'),
|
|
28
|
+
controllers:
|
|
29
|
+
process.env.TEST_FOLDER_CONTROLLERS || path.resolve('./controllers'),
|
|
30
|
+
views: process.env.TEST_FOLDER_VIEWS || path.resolve('./views'),
|
|
31
|
+
public: process.env.TEST_FOLDER_PUBLIC || path.resolve('./public'),
|
|
32
|
+
models: process.env.TEST_FOLDER_MODELS || path.resolve('./models'),
|
|
33
|
+
emails:
|
|
34
|
+
process.env.TEST_FOLDER_EMAIL ||
|
|
35
|
+
process.env.TEST_FOLDER_EMAILS ||
|
|
36
|
+
path.resolve('./services/messaging/email/templates'),
|
|
37
|
+
locales: process.env.TEST_FOLDER_LOCALES || path.resolve('./locales'),
|
|
38
|
+
commands: process.env.TEST_FOLDER_COMMANDS || path.resolve('./commands'),
|
|
39
|
+
migrations:
|
|
40
|
+
process.env.TEST_FOLDER_MIGRATIONS || path.resolve('./migrations'),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
global.server.updateConfig('mongo', {
|
|
44
|
+
connectionString: connectionStringMongo,
|
|
45
|
+
});
|
|
46
|
+
global.server.updateConfig('http', { port: 0 }); // allow to use random
|
|
47
|
+
global.server.updateConfig('mail', { transport: 'stub' });
|
|
48
|
+
if (!global.testSetup) {
|
|
49
|
+
global.testSetup = {};
|
|
50
|
+
}
|
|
51
|
+
global.server.testingGetUrl = (urlPart) =>
|
|
52
|
+
`http://127.0.0.1:${global.server.getConfig('http').port}${urlPart}`;
|
|
53
|
+
if (!global.testSetup.disableUserCreate) {
|
|
54
|
+
const User = global.server.app.getModel('User');
|
|
55
|
+
global.user = await User.create({
|
|
56
|
+
email: 'test@test.com',
|
|
57
|
+
password: 'testPassword',
|
|
58
|
+
isVerified: true,
|
|
59
|
+
name: {
|
|
60
|
+
nick: 'testUserNickName',
|
|
61
|
+
},
|
|
62
|
+
}).catch((e) => {
|
|
63
|
+
// eslint-disable-next-line no-console
|
|
64
|
+
console.error(e);
|
|
65
|
+
// eslint-disable-next-line no-console
|
|
66
|
+
console.info(
|
|
67
|
+
'That error can happens in case you have custom user model. Please use global.testSetup.disableUserCreate flag to skip user creating',
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
global.authToken = await global.user.generateToken();
|
|
71
|
+
}
|
|
72
|
+
if (typeof global.testSetup.beforeAll === 'function') {
|
|
73
|
+
await global.testSetup.beforeAll();
|
|
74
|
+
}
|
|
75
|
+
await global.server.startServer();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
|
|
79
|
+
beforeEach(() => {
|
|
80
|
+
if (global.server) {
|
|
81
|
+
const key = `test-${Math.random().toString(36).substring(7)}`;
|
|
82
|
+
global.server.app.updateConfig('redis', {
|
|
83
|
+
namespace: key,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
|
|
89
|
+
afterEach(async () => {
|
|
90
|
+
if (global.server) {
|
|
91
|
+
const { url, namespace } = global.server.getConfig('redis');
|
|
92
|
+
const redisClient = redis.createClient({ url });
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await redisClient.connect();
|
|
96
|
+
await clearRedisNamespace(redisClient, namespace);
|
|
97
|
+
await redisClient.disconnect();
|
|
98
|
+
} catch (err) {
|
|
99
|
+
// that ok. No redis connection
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
|
|
105
|
+
afterAll(async () => {
|
|
106
|
+
if (global.server) {
|
|
107
|
+
global.server.app.httpServer.shutdown();
|
|
108
|
+
global.server.app.events.emit('shutdown');
|
|
109
|
+
}
|
|
110
|
+
// setTimeout(async () => {
|
|
111
|
+
if (typeof global.testSetup.afterAll === 'function') {
|
|
112
|
+
await global.testSetup.afterAll();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await mongoose.disconnect();
|
|
116
|
+
await mongoMemoryServerInstance.stop();
|
|
117
|
+
|
|
118
|
+
// }, 2000);
|
|
119
|
+
});
|
package/vitest.config.js
ADDED
package/babel.config.js
DELETED