@opra/testing 1.21.0 → 1.22.1
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/{esm/api-expect → api-expect}/api-expect-base.js +2 -0
- package/package.json +10 -27
- package/{esm/test-backend.js → test-backend.js} +1 -0
- package/cjs/api-expect/api-expect-base.js +0 -18
- package/cjs/api-expect/api-expect-collection.js +0 -272
- package/cjs/api-expect/api-expect-error.js +0 -29
- package/cjs/api-expect/api-expect-object.js +0 -75
- package/cjs/api-expect/api-expect-operation-result.js +0 -28
- package/cjs/api-expect/api-expect.js +0 -167
- package/cjs/expect-extend/common.extend.js +0 -75
- package/cjs/expect-extend/index.js +0 -4
- package/cjs/index.js +0 -5
- package/cjs/package.json +0 -3
- package/cjs/test-backend.js +0 -63
- package/cjs/test-client.js +0 -12
- package/cjs/utils/object-matches.util.js +0 -35
- package/esm/package.json +0 -3
- package/types/index.d.cts +0 -2
- /package/{types/api-expect → api-expect}/api-expect-base.d.ts +0 -0
- /package/{types/api-expect → api-expect}/api-expect-collection.d.ts +0 -0
- /package/{esm/api-expect → api-expect}/api-expect-collection.js +0 -0
- /package/{types/api-expect → api-expect}/api-expect-error.d.ts +0 -0
- /package/{esm/api-expect → api-expect}/api-expect-error.js +0 -0
- /package/{types/api-expect → api-expect}/api-expect-object.d.ts +0 -0
- /package/{esm/api-expect → api-expect}/api-expect-object.js +0 -0
- /package/{types/api-expect → api-expect}/api-expect-operation-result.d.ts +0 -0
- /package/{esm/api-expect → api-expect}/api-expect-operation-result.js +0 -0
- /package/{types/api-expect → api-expect}/api-expect.d.ts +0 -0
- /package/{esm/api-expect → api-expect}/api-expect.js +0 -0
- /package/{types/expect-extend → expect-extend}/common.extend.d.ts +0 -0
- /package/{esm/expect-extend → expect-extend}/common.extend.js +0 -0
- /package/{types/expect-extend → expect-extend}/index.d.ts +0 -0
- /package/{esm/expect-extend → expect-extend}/index.js +0 -0
- /package/{types/index.d.ts → index.d.ts} +0 -0
- /package/{esm/index.js → index.js} +0 -0
- /package/{types/test-backend.d.ts → test-backend.d.ts} +0 -0
- /package/{types/test-client.d.ts → test-client.d.ts} +0 -0
- /package/{esm/test-client.js → test-client.js} +0 -0
- /package/{types/utils → utils}/object-matches.util.d.ts +0 -0
- /package/{esm/utils → utils}/object-matches.util.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/testing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.1",
|
|
4
4
|
"description": "Opra testing package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,46 +12,29 @@
|
|
|
12
12
|
"tslib": "^2.8.1"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@opra/client": "^1.
|
|
16
|
-
"@opra/common": "^1.
|
|
15
|
+
"@opra/client": "^1.22.1",
|
|
16
|
+
"@opra/common": "^1.22.1",
|
|
17
17
|
"expect": "^29.0.0 || ^30.0.0",
|
|
18
18
|
"jest-matcher-utils": "^29.0.0 || ^30.0.0"
|
|
19
19
|
},
|
|
20
20
|
"type": "module",
|
|
21
|
+
"module": "./index.js",
|
|
22
|
+
"types": "./index.d.ts",
|
|
21
23
|
"exports": {
|
|
22
24
|
".": {
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
"default": "./esm/index.js"
|
|
26
|
-
},
|
|
27
|
-
"require": {
|
|
28
|
-
"types": "./types/index.d.cts",
|
|
29
|
-
"default": "./cjs/index.js"
|
|
30
|
-
},
|
|
31
|
-
"default": "./esm/index.js"
|
|
25
|
+
"types": "./index.d.ts",
|
|
26
|
+
"default": "./index.js"
|
|
32
27
|
},
|
|
33
28
|
"./package.json": "./package.json"
|
|
34
29
|
},
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20.0"
|
|
32
|
+
},
|
|
38
33
|
"repository": {
|
|
39
34
|
"type": "git",
|
|
40
35
|
"url": "git+https://github.com/panates/opra.git",
|
|
41
36
|
"directory": "packages/testing"
|
|
42
37
|
},
|
|
43
|
-
"engines": {
|
|
44
|
-
"node": ">=16.0",
|
|
45
|
-
"npm": ">=7.0.0"
|
|
46
|
-
},
|
|
47
|
-
"files": [
|
|
48
|
-
"bin/",
|
|
49
|
-
"cjs/",
|
|
50
|
-
"esm/",
|
|
51
|
-
"types/",
|
|
52
|
-
"LICENSE",
|
|
53
|
-
"README.md"
|
|
54
|
-
],
|
|
55
38
|
"keywords": [
|
|
56
39
|
"opra",
|
|
57
40
|
"testing"
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApiExpectBase = void 0;
|
|
4
|
-
require("../expect-extend/index.js");
|
|
5
|
-
const expect_1 = require("expect");
|
|
6
|
-
class ApiExpectBase {
|
|
7
|
-
constructor(response, isNot) {
|
|
8
|
-
this.response = response;
|
|
9
|
-
this.isNot = isNot;
|
|
10
|
-
}
|
|
11
|
-
_expect(expected) {
|
|
12
|
-
const out = (0, expect_1.expect)(expected);
|
|
13
|
-
if (this.isNot)
|
|
14
|
-
return out.not;
|
|
15
|
-
return out;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.ApiExpectBase = ApiExpectBase;
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApiExpectCollection = void 0;
|
|
4
|
-
exports.convertFilter = convertFilter;
|
|
5
|
-
const tslib_1 = require("tslib");
|
|
6
|
-
const type_is_1 = tslib_1.__importDefault(require("@browsery/type-is"));
|
|
7
|
-
const objects_1 = require("@jsopen/objects");
|
|
8
|
-
const common_1 = require("@opra/common");
|
|
9
|
-
const expect_1 = require("expect");
|
|
10
|
-
const rule_judgment_1 = tslib_1.__importDefault(require("rule-judgment"));
|
|
11
|
-
const api_expect_base_js_1 = require("./api-expect-base.js");
|
|
12
|
-
const ruleJudgment = typeof rule_judgment_1.default === 'object'
|
|
13
|
-
? rule_judgment_1.default.default
|
|
14
|
-
: rule_judgment_1.default;
|
|
15
|
-
class ApiExpectCollection extends api_expect_base_js_1.ApiExpectBase {
|
|
16
|
-
get not() {
|
|
17
|
-
return new ApiExpectCollection(this.response, !this.isNot);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Tests if Collection have number of items in payload
|
|
21
|
-
* @param min Minimum number of items. Default 1
|
|
22
|
-
* @param max Maximum number of items
|
|
23
|
-
*/
|
|
24
|
-
toReturnItems(min, max) {
|
|
25
|
-
let msg = '';
|
|
26
|
-
try {
|
|
27
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
28
|
-
common_1.MimeTypes.opra_response_json,
|
|
29
|
-
])
|
|
30
|
-
? this.response.body.payload
|
|
31
|
-
: this.response.body;
|
|
32
|
-
msg += `Payload should be array.`;
|
|
33
|
-
this._expect(Array.isArray(data)).toBeTruthy();
|
|
34
|
-
msg += `The length of payload array do not match. `;
|
|
35
|
-
const l = data.length;
|
|
36
|
-
this._expect(l).toBeGreaterThanOrEqual(min || 1);
|
|
37
|
-
if (max)
|
|
38
|
-
this._expect(l).toBeLessThanOrEqual(max);
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
if (msg)
|
|
42
|
-
e.message = msg + '\n\n' + e.message;
|
|
43
|
-
Error.captureStackTrace(e, this.toReturnItems);
|
|
44
|
-
throw e;
|
|
45
|
-
}
|
|
46
|
-
return this;
|
|
47
|
-
}
|
|
48
|
-
toContainTotalMatches(min, max) {
|
|
49
|
-
let msg = '';
|
|
50
|
-
try {
|
|
51
|
-
msg += `The value of "totalMatches" do not match. `;
|
|
52
|
-
const l = this.response.body.totalMatches;
|
|
53
|
-
this._expect(l).toBeGreaterThanOrEqual(min || 1);
|
|
54
|
-
if (max)
|
|
55
|
-
this._expect(l).toBeLessThanOrEqual(max);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
if (msg)
|
|
59
|
-
e.message = msg + '\n\n' + e.message;
|
|
60
|
-
Error.captureStackTrace(e, this.toReturnItems);
|
|
61
|
-
throw e;
|
|
62
|
-
}
|
|
63
|
-
return this;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Tests if Collection items matches given object
|
|
67
|
-
* @param expected
|
|
68
|
-
*/
|
|
69
|
-
toMatch(expected) {
|
|
70
|
-
try {
|
|
71
|
-
expected = (0, objects_1.omitNullish)(expected);
|
|
72
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
73
|
-
common_1.MimeTypes.opra_response_json,
|
|
74
|
-
])
|
|
75
|
-
? this.response.body.payload
|
|
76
|
-
: this.response.body;
|
|
77
|
-
for (const x of data) {
|
|
78
|
-
this._expect(x).toMatchObject(expected);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
Error.captureStackTrace(e, this.toMatch);
|
|
83
|
-
throw e;
|
|
84
|
-
}
|
|
85
|
-
return this;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Tests if Collection items has all of provided fields.
|
|
89
|
-
* @param fields
|
|
90
|
-
*/
|
|
91
|
-
toContainFields(fields) {
|
|
92
|
-
try {
|
|
93
|
-
fields = Array.isArray(fields) ? fields : [fields];
|
|
94
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
95
|
-
common_1.MimeTypes.opra_response_json,
|
|
96
|
-
])
|
|
97
|
-
? this.response.body.payload
|
|
98
|
-
: this.response.body;
|
|
99
|
-
for (const item of data) {
|
|
100
|
-
this._expect(Object.keys(item)).toEqual(expect_1.expect.arrayContaining(fields));
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch (e) {
|
|
104
|
-
Error.captureStackTrace(e, this.toContainFields);
|
|
105
|
-
throw e;
|
|
106
|
-
}
|
|
107
|
-
return this;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Tests if Collection items only contains all of provided fields.
|
|
111
|
-
* @param fields
|
|
112
|
-
*/
|
|
113
|
-
toContainAllFields(fields) {
|
|
114
|
-
try {
|
|
115
|
-
fields = Array.isArray(fields) ? fields : [fields];
|
|
116
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
117
|
-
common_1.MimeTypes.opra_response_json,
|
|
118
|
-
])
|
|
119
|
-
? this.response.body.payload
|
|
120
|
-
: this.response.body;
|
|
121
|
-
for (const item of data) {
|
|
122
|
-
this._expect(Object.keys(item)).toEqual(fields);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
catch (e) {
|
|
126
|
-
Error.captureStackTrace(e, this.toContainAllFields);
|
|
127
|
-
throw e;
|
|
128
|
-
}
|
|
129
|
-
return this;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Tests if Collection is sorted by given field(s).
|
|
133
|
-
* @param fields
|
|
134
|
-
*/
|
|
135
|
-
toBeSortedBy(fields) {
|
|
136
|
-
try {
|
|
137
|
-
fields = Array.isArray(fields) ? fields : [fields];
|
|
138
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
139
|
-
common_1.MimeTypes.opra_response_json,
|
|
140
|
-
])
|
|
141
|
-
? this.response.body.payload
|
|
142
|
-
: this.response.body;
|
|
143
|
-
this._expect(data).opraCollectionToBeSortedBy(fields);
|
|
144
|
-
}
|
|
145
|
-
catch (e) {
|
|
146
|
-
Error.captureStackTrace(e, this.toBeSortedBy);
|
|
147
|
-
throw e;
|
|
148
|
-
}
|
|
149
|
-
return this;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Tests if Collection is filtered by given condition.
|
|
153
|
-
* @param filter
|
|
154
|
-
*/
|
|
155
|
-
toBeFilteredBy(filter) {
|
|
156
|
-
const f = convertFilter(filter);
|
|
157
|
-
if (f) {
|
|
158
|
-
const j = ruleJudgment(f);
|
|
159
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
160
|
-
common_1.MimeTypes.opra_response_json,
|
|
161
|
-
])
|
|
162
|
-
? this.response.body.payload
|
|
163
|
-
: this.response.body;
|
|
164
|
-
const filtered = data.filter(j);
|
|
165
|
-
try {
|
|
166
|
-
this._expect(data).toStrictEqual(filtered);
|
|
167
|
-
}
|
|
168
|
-
catch (e) {
|
|
169
|
-
Error.captureStackTrace(e, this.toBeFilteredBy);
|
|
170
|
-
throw e;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return this;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
exports.ApiExpectCollection = ApiExpectCollection;
|
|
177
|
-
expect_1.expect.extend({
|
|
178
|
-
opraCollectionToBeSortedBy(received, properties) {
|
|
179
|
-
const fieldsMap = properties.map(x => x.split('.'));
|
|
180
|
-
const getValue = (obj, fieldMap) => {
|
|
181
|
-
let v = obj;
|
|
182
|
-
let i = 0;
|
|
183
|
-
while (v && i < fieldMap.length) {
|
|
184
|
-
v = v[fieldMap[i++]];
|
|
185
|
-
}
|
|
186
|
-
return v;
|
|
187
|
-
};
|
|
188
|
-
let pass = true;
|
|
189
|
-
let message;
|
|
190
|
-
if (pass) {
|
|
191
|
-
const sorted = [...(received || [])];
|
|
192
|
-
sorted.sort((a, b) => {
|
|
193
|
-
for (const sortField of fieldsMap) {
|
|
194
|
-
const l = getValue(a, sortField);
|
|
195
|
-
const r = getValue(b, sortField);
|
|
196
|
-
if (l < r)
|
|
197
|
-
return -1;
|
|
198
|
-
if (l > r)
|
|
199
|
-
return 1;
|
|
200
|
-
}
|
|
201
|
-
return 0;
|
|
202
|
-
});
|
|
203
|
-
try {
|
|
204
|
-
(0, expect_1.expect)(received).toEqual(sorted);
|
|
205
|
-
}
|
|
206
|
-
catch {
|
|
207
|
-
pass = false;
|
|
208
|
-
message = () => 'Items are not sorted as expected';
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return {
|
|
212
|
-
actual: received,
|
|
213
|
-
message,
|
|
214
|
-
pass,
|
|
215
|
-
};
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
function convertFilter(str) {
|
|
219
|
-
const ast = typeof str === 'string' ? common_1.OpraFilter.parse(str) : str;
|
|
220
|
-
if (!ast)
|
|
221
|
-
return;
|
|
222
|
-
if (ast instanceof common_1.OpraFilter.ComparisonExpression) {
|
|
223
|
-
const left = convertFilter(ast.left);
|
|
224
|
-
const right = convertFilter(ast.right);
|
|
225
|
-
switch (ast.op) {
|
|
226
|
-
case '=':
|
|
227
|
-
return { $eq: { [left]: right } };
|
|
228
|
-
case '!=':
|
|
229
|
-
return { $ne: { [left]: right } };
|
|
230
|
-
case '>':
|
|
231
|
-
return { $gt: { [left]: right } };
|
|
232
|
-
case '>=':
|
|
233
|
-
return { $gte: { [left]: right } };
|
|
234
|
-
case '<':
|
|
235
|
-
return { $lt: { [left]: right } };
|
|
236
|
-
case '<=':
|
|
237
|
-
return { $lte: { [left]: right } };
|
|
238
|
-
case 'in':
|
|
239
|
-
return { $in: { [left]: right } };
|
|
240
|
-
case '!in':
|
|
241
|
-
return { $nin: { [left]: right } };
|
|
242
|
-
default:
|
|
243
|
-
throw new Error(`ComparisonExpression operator (${ast.op}) not implemented yet`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
if (ast instanceof common_1.OpraFilter.QualifiedIdentifier) {
|
|
247
|
-
return ast.value;
|
|
248
|
-
}
|
|
249
|
-
if (ast instanceof common_1.OpraFilter.NumberLiteral ||
|
|
250
|
-
ast instanceof common_1.OpraFilter.StringLiteral ||
|
|
251
|
-
ast instanceof common_1.OpraFilter.BooleanLiteral ||
|
|
252
|
-
ast instanceof common_1.OpraFilter.NullLiteral ||
|
|
253
|
-
ast instanceof common_1.OpraFilter.DateLiteral ||
|
|
254
|
-
ast instanceof common_1.OpraFilter.TimeLiteral) {
|
|
255
|
-
return ast.value;
|
|
256
|
-
}
|
|
257
|
-
if (ast instanceof common_1.OpraFilter.ArrayExpression) {
|
|
258
|
-
return ast.items.map(convertFilter);
|
|
259
|
-
}
|
|
260
|
-
if (ast instanceof common_1.OpraFilter.LogicalExpression) {
|
|
261
|
-
if (ast.op === 'or')
|
|
262
|
-
return { $or: ast.items.map(convertFilter) };
|
|
263
|
-
return { $and: ast.items.map(convertFilter) };
|
|
264
|
-
}
|
|
265
|
-
if (ast instanceof common_1.OpraFilter.ArrayExpression) {
|
|
266
|
-
return ast.items.map(convertFilter);
|
|
267
|
-
}
|
|
268
|
-
if (ast instanceof common_1.OpraFilter.ParenthesizedExpression) {
|
|
269
|
-
return convertFilter(ast.expression);
|
|
270
|
-
}
|
|
271
|
-
throw new Error(`${ast.kind} is not implemented yet`);
|
|
272
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApiExpectError = void 0;
|
|
4
|
-
require("../expect-extend/index.js");
|
|
5
|
-
const objects_1 = require("@jsopen/objects");
|
|
6
|
-
const expect_1 = require("expect");
|
|
7
|
-
const api_expect_base_js_1 = require("./api-expect-base.js");
|
|
8
|
-
class ApiExpectError extends api_expect_base_js_1.ApiExpectBase {
|
|
9
|
-
toMatch(expected) {
|
|
10
|
-
try {
|
|
11
|
-
if (typeof expected === 'string')
|
|
12
|
-
expected = { message: expected };
|
|
13
|
-
else if (expected instanceof RegExp) {
|
|
14
|
-
expected = {
|
|
15
|
-
message: expect_1.expect.stringMatching(expected),
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
else
|
|
19
|
-
expected = (0, objects_1.omitNullish)(expected);
|
|
20
|
-
this._expect(this.response.body.errors).toEqual(expect_1.expect.arrayContaining([expect_1.expect.objectContaining(expected)]));
|
|
21
|
-
}
|
|
22
|
-
catch (e) {
|
|
23
|
-
Error.captureStackTrace(e, this.toMatch);
|
|
24
|
-
throw e;
|
|
25
|
-
}
|
|
26
|
-
return this;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.ApiExpectError = ApiExpectError;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApiExpectObject = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const type_is_1 = tslib_1.__importDefault(require("@browsery/type-is"));
|
|
6
|
-
const objects_1 = require("@jsopen/objects");
|
|
7
|
-
const common_1 = require("@opra/common");
|
|
8
|
-
const expect_1 = require("expect");
|
|
9
|
-
const api_expect_base_js_1 = require("./api-expect-base.js");
|
|
10
|
-
class ApiExpectObject extends api_expect_base_js_1.ApiExpectBase {
|
|
11
|
-
get not() {
|
|
12
|
-
return new ApiExpectObject(this.response, !this.isNot);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Tests if Response payload matches given object
|
|
16
|
-
* @param expected
|
|
17
|
-
*/
|
|
18
|
-
toMatch(expected) {
|
|
19
|
-
try {
|
|
20
|
-
expected = (0, objects_1.omitNullish)(expected);
|
|
21
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
22
|
-
common_1.MimeTypes.opra_response_json,
|
|
23
|
-
])
|
|
24
|
-
? this.response.body.payload
|
|
25
|
-
: this.response.body;
|
|
26
|
-
this._expect(data).toEqual(expect_1.expect.objectContaining(expected));
|
|
27
|
-
}
|
|
28
|
-
catch (e) {
|
|
29
|
-
Error.captureStackTrace(e, this.toMatch);
|
|
30
|
-
throw e;
|
|
31
|
-
}
|
|
32
|
-
return this;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Tests if Response payload has all of provided fields.
|
|
36
|
-
* @param fields
|
|
37
|
-
*/
|
|
38
|
-
toContainFields(fields) {
|
|
39
|
-
try {
|
|
40
|
-
fields = Array.isArray(fields) ? fields : [fields];
|
|
41
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
42
|
-
common_1.MimeTypes.opra_response_json,
|
|
43
|
-
])
|
|
44
|
-
? this.response.body.payload
|
|
45
|
-
: this.response.body;
|
|
46
|
-
this._expect(Object.keys(data)).toEqual(expect_1.expect.arrayContaining(fields));
|
|
47
|
-
}
|
|
48
|
-
catch (e) {
|
|
49
|
-
Error.captureStackTrace(e, this.toContainFields);
|
|
50
|
-
throw e;
|
|
51
|
-
}
|
|
52
|
-
return this;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Tests if Response payload only contains all of provided fields.
|
|
56
|
-
* @param fields
|
|
57
|
-
*/
|
|
58
|
-
toContainAllFields(fields) {
|
|
59
|
-
try {
|
|
60
|
-
fields = Array.isArray(fields) ? fields : [fields];
|
|
61
|
-
const data = type_is_1.default.is(this.response.contentType, [
|
|
62
|
-
common_1.MimeTypes.opra_response_json,
|
|
63
|
-
])
|
|
64
|
-
? this.response.body.payload
|
|
65
|
-
: this.response.body;
|
|
66
|
-
this._expect(Object.keys(data)).toEqual(fields);
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
Error.captureStackTrace(e, this.toContainAllFields);
|
|
70
|
-
throw e;
|
|
71
|
-
}
|
|
72
|
-
return this;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
exports.ApiExpectObject = ApiExpectObject;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApiExpectOperationResult = void 0;
|
|
4
|
-
require("../expect-extend/index.js");
|
|
5
|
-
const api_expect_base_js_1 = require("./api-expect-base.js");
|
|
6
|
-
class ApiExpectOperationResult extends api_expect_base_js_1.ApiExpectBase {
|
|
7
|
-
get not() {
|
|
8
|
-
return new ApiExpectOperationResult(this.response, !this.isNot);
|
|
9
|
-
}
|
|
10
|
-
toBeAffected(min, max) {
|
|
11
|
-
let msg = '';
|
|
12
|
-
try {
|
|
13
|
-
msg += `The value of "affected" do not match. `;
|
|
14
|
-
const l = this.response.body.affected;
|
|
15
|
-
this._expect(l).toBeGreaterThanOrEqual(min || 1);
|
|
16
|
-
if (max)
|
|
17
|
-
this._expect(l).toBeLessThanOrEqual(max);
|
|
18
|
-
}
|
|
19
|
-
catch (e) {
|
|
20
|
-
if (msg)
|
|
21
|
-
e.message = msg + '\n\n' + e.message;
|
|
22
|
-
Error.captureStackTrace(e, this.toBeAffected);
|
|
23
|
-
throw e;
|
|
24
|
-
}
|
|
25
|
-
return this;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
exports.ApiExpectOperationResult = ApiExpectOperationResult;
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApiExpect = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
require("../expect-extend/index.js");
|
|
6
|
-
const common_1 = require("@opra/common");
|
|
7
|
-
const ansi_colors_1 = tslib_1.__importDefault(require("ansi-colors"));
|
|
8
|
-
const expect_1 = require("expect");
|
|
9
|
-
const api_expect_base_js_1 = require("./api-expect-base.js");
|
|
10
|
-
const api_expect_collection_js_1 = require("./api-expect-collection.js");
|
|
11
|
-
const api_expect_error_js_1 = require("./api-expect-error.js");
|
|
12
|
-
const api_expect_object_js_1 = require("./api-expect-object.js");
|
|
13
|
-
const api_expect_operation_result_js_1 = require("./api-expect-operation-result.js");
|
|
14
|
-
class ApiExpect extends api_expect_base_js_1.ApiExpectBase {
|
|
15
|
-
/**
|
|
16
|
-
* Tests if request succeeded
|
|
17
|
-
* @param status Status code number between 200-299
|
|
18
|
-
*/
|
|
19
|
-
toSuccess(status) {
|
|
20
|
-
let msg = '';
|
|
21
|
-
try {
|
|
22
|
-
msg += `Status code do not match. `;
|
|
23
|
-
if (status) {
|
|
24
|
-
(0, expect_1.expect)(this.response.status).toEqual(status);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
(0, expect_1.expect)(this.response.status).toBeGreaterThanOrEqual(200);
|
|
28
|
-
(0, expect_1.expect)(this.response.status).toBeLessThan(400);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
e.message =
|
|
33
|
-
"Request didn't succeeded as expected. " + msg + '\n\n' + e.message;
|
|
34
|
-
const issues = this.response.body?.errors;
|
|
35
|
-
if (issues) {
|
|
36
|
-
e.message += '\n\n';
|
|
37
|
-
issues.forEach((issue, i) => {
|
|
38
|
-
const stack = Array.isArray(issue.stack)
|
|
39
|
-
? issue.stack.join('\n')
|
|
40
|
-
: issue.stack;
|
|
41
|
-
e.message +=
|
|
42
|
-
ansi_colors_1.default.yellow(issues.length > 1 ? `Error [${i}]: ` : 'Error: ') +
|
|
43
|
-
issue.message +
|
|
44
|
-
'\n' +
|
|
45
|
-
(stack
|
|
46
|
-
? ' ' + stack.substring(stack.indexOf('at ')) + '\n'
|
|
47
|
-
: '');
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
Error.captureStackTrace(e, this.toSuccess);
|
|
51
|
-
throw e;
|
|
52
|
-
}
|
|
53
|
-
return this;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Tests if request failed
|
|
57
|
-
* @param status Status code number between 400-599
|
|
58
|
-
*/
|
|
59
|
-
toFail(status) {
|
|
60
|
-
let msg = '';
|
|
61
|
-
try {
|
|
62
|
-
msg += `Status code do not match. `;
|
|
63
|
-
if (status) {
|
|
64
|
-
(0, expect_1.expect)(this.response.status).toEqual(status);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
(0, expect_1.expect)(this.response.status).toBeGreaterThanOrEqual(400);
|
|
68
|
-
(0, expect_1.expect)(this.response.status).toBeLessThanOrEqual(599);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
catch (e) {
|
|
72
|
-
e.message =
|
|
73
|
-
"Request didn't failed as expected. " + msg + '\n\n' + e.message;
|
|
74
|
-
const issues = this.response.body?.errors;
|
|
75
|
-
if (issues) {
|
|
76
|
-
e.message += '\n\n';
|
|
77
|
-
issues.forEach((issue, i) => {
|
|
78
|
-
const stack = Array.isArray(issue.stack)
|
|
79
|
-
? issue.stack.join('\n')
|
|
80
|
-
: issue.stack;
|
|
81
|
-
e.message +=
|
|
82
|
-
ansi_colors_1.default.yellow(issues.length > 1 ? `Error [${i}]: ` : 'Error: ') +
|
|
83
|
-
issue.message +
|
|
84
|
-
'\n' +
|
|
85
|
-
(stack
|
|
86
|
-
? ' ' + stack.substring(stack.indexOf('at ')) + '\n'
|
|
87
|
-
: '');
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
Error.captureStackTrace(e, this.toSuccess);
|
|
91
|
-
throw e;
|
|
92
|
-
}
|
|
93
|
-
return new api_expect_error_js_1.ApiExpectError(this.response);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Tests if API returns a Collection
|
|
97
|
-
*/
|
|
98
|
-
toReturnCollection() {
|
|
99
|
-
let msg = '';
|
|
100
|
-
try {
|
|
101
|
-
msg = 'Content-Type header value is not valid. ';
|
|
102
|
-
(0, expect_1.expect)(this.response.contentType).toEqual('application/opra.response+json');
|
|
103
|
-
msg = 'Type of response "body" is not valid. ';
|
|
104
|
-
(0, expect_1.expect)(typeof this.response.body).toEqual('object');
|
|
105
|
-
msg = 'Type of "payload" is not an Array. ';
|
|
106
|
-
const payload = this.response.body.payload;
|
|
107
|
-
(0, expect_1.expect)(Array.isArray(payload) ? 'array' : typeof payload).toEqual('array');
|
|
108
|
-
}
|
|
109
|
-
catch (e) {
|
|
110
|
-
e.message =
|
|
111
|
-
"Api didn't returned a Collection. " + msg + '\n\n' + e.message;
|
|
112
|
-
if (msg)
|
|
113
|
-
e.message = msg + '\n\n' + e.message;
|
|
114
|
-
Error.captureStackTrace(e, this.toReturnCollection);
|
|
115
|
-
throw e;
|
|
116
|
-
}
|
|
117
|
-
return new api_expect_collection_js_1.ApiExpectCollection(this.response);
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Tests if API returns an Object
|
|
121
|
-
*/
|
|
122
|
-
toReturnObject(contentType) {
|
|
123
|
-
let msg = '';
|
|
124
|
-
try {
|
|
125
|
-
msg = 'Content-Type header value is not valid. ';
|
|
126
|
-
(0, expect_1.expect)(this.response.contentType).toEqual(contentType || common_1.MimeTypes.opra_response_json);
|
|
127
|
-
msg = 'Type of response "body" is not valid. ';
|
|
128
|
-
(0, expect_1.expect)(typeof this.response.body).toEqual('object');
|
|
129
|
-
msg = 'Type of "payload" is not an Object. ';
|
|
130
|
-
const payload = this.response.body.payload;
|
|
131
|
-
(0, expect_1.expect)(typeof payload).toEqual('object');
|
|
132
|
-
}
|
|
133
|
-
catch (e) {
|
|
134
|
-
e.message = "Api didn't returned an Object. " + msg + '\n\n' + e.message;
|
|
135
|
-
if (msg)
|
|
136
|
-
e.message = msg + '\n\n' + e.message;
|
|
137
|
-
Error.captureStackTrace(e, this.toReturnCollection);
|
|
138
|
-
throw e;
|
|
139
|
-
}
|
|
140
|
-
return new api_expect_object_js_1.ApiExpectObject(this.response);
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Tests if API returns an OperationResult
|
|
144
|
-
*/
|
|
145
|
-
toReturnOperationResult() {
|
|
146
|
-
let msg = '';
|
|
147
|
-
try {
|
|
148
|
-
msg = 'Content-Type header value is not valid. ';
|
|
149
|
-
(0, expect_1.expect)(this.response.contentType).toEqual(common_1.MimeTypes.opra_response_json);
|
|
150
|
-
msg = 'Type of response "body" is not valid. ';
|
|
151
|
-
(0, expect_1.expect)(typeof this.response.body).toEqual('object');
|
|
152
|
-
msg = 'The response has payload. ';
|
|
153
|
-
const payload = this.response.body.payload;
|
|
154
|
-
(0, expect_1.expect)(typeof payload).toEqual('undefined');
|
|
155
|
-
}
|
|
156
|
-
catch (e) {
|
|
157
|
-
e.message =
|
|
158
|
-
"Api didn't returned a OperationResult. " + msg + '\n\n' + e.message;
|
|
159
|
-
if (msg)
|
|
160
|
-
e.message = msg + '\n\n' + e.message;
|
|
161
|
-
Error.captureStackTrace(e, this.toReturnCollection);
|
|
162
|
-
throw e;
|
|
163
|
-
}
|
|
164
|
-
return new api_expect_operation_result_js_1.ApiExpectOperationResult(this.response);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
exports.ApiExpect = ApiExpect;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const ansi_colors_1 = tslib_1.__importDefault(require("ansi-colors"));
|
|
5
|
-
const expect_1 = require("expect");
|
|
6
|
-
const jest_matcher_utils_1 = require("jest-matcher-utils");
|
|
7
|
-
expect_1.expect.extend({
|
|
8
|
-
toHaveFields(received, expected) {
|
|
9
|
-
const expectedKeys = (Array.isArray(expected) ? expected : Object.keys(expected)).map(x => x.toLowerCase());
|
|
10
|
-
const objectKeys = Object.keys(received).map(x => x.toLowerCase());
|
|
11
|
-
const filteredKeys = expectedKeys.filter(x => !objectKeys.includes(x));
|
|
12
|
-
const pass = !filteredKeys.length === !this.isNot;
|
|
13
|
-
if (!pass) {
|
|
14
|
-
const message = () => `Expects keys ${this.isNot ? 'not ' : ''}to contain: ${ansi_colors_1.default.yellow('' + expectedKeys)}\n` +
|
|
15
|
-
`${this.isNot ? 'Unsolicited' : 'Missing'} fields: ${ansi_colors_1.default.yellow('' + filteredKeys)}\n`;
|
|
16
|
-
return { message, pass: !!this.isNot };
|
|
17
|
-
}
|
|
18
|
-
return { actual: received, pass: !this.isNot, message: () => '' };
|
|
19
|
-
},
|
|
20
|
-
toHaveFieldsOnly(received, expected) {
|
|
21
|
-
const expectedKeys = (Array.isArray(expected) ? expected : Object.keys(expected)).map(x => x.toLowerCase());
|
|
22
|
-
const objectKeys = Object.keys(received).map(x => x.toLowerCase());
|
|
23
|
-
const filteredKeys = objectKeys.filter(x => !expectedKeys.includes(x));
|
|
24
|
-
const pass = !filteredKeys.length === !this.isNot;
|
|
25
|
-
if (!pass) {
|
|
26
|
-
const message = () => `${!this.isNot ? 'Do not expects' : 'Expects'} additional keys other than: ${ansi_colors_1.default.yellow('' + expectedKeys)}\n` +
|
|
27
|
-
(filteredKeys
|
|
28
|
-
? `Additional keys received: ${ansi_colors_1.default.yellow('' + filteredKeys)}\n`
|
|
29
|
-
: 'No additional keys received\n');
|
|
30
|
-
return { message, pass };
|
|
31
|
-
}
|
|
32
|
-
return { actual: received, pass: !this.isNot, message: () => '' };
|
|
33
|
-
},
|
|
34
|
-
toBeArray(received) {
|
|
35
|
-
if (Array.isArray(received)) {
|
|
36
|
-
return { actual: received, pass: true, message: () => '' };
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
pass: false,
|
|
40
|
-
message: () => 'Value is not an array',
|
|
41
|
-
};
|
|
42
|
-
},
|
|
43
|
-
toBeGreaterThanAny(received, expected) {
|
|
44
|
-
return compare('toBeGreaterThan', {
|
|
45
|
-
isNot: this.isNot,
|
|
46
|
-
promise: this.promise,
|
|
47
|
-
}, received, expected, '>', () => received > expected);
|
|
48
|
-
},
|
|
49
|
-
toBeGreaterThanOrEqualAny(received, expected) {
|
|
50
|
-
return compare('toBeGreaterThanOrEqual', {
|
|
51
|
-
isNot: this.isNot,
|
|
52
|
-
promise: this.promise,
|
|
53
|
-
}, received, expected, '>=', () => received >= expected);
|
|
54
|
-
},
|
|
55
|
-
toBeLessThanAny(received, expected) {
|
|
56
|
-
return compare('toBeLessThan', {
|
|
57
|
-
isNot: this.isNot,
|
|
58
|
-
promise: this.promise,
|
|
59
|
-
}, received, expected, '<', () => received < expected);
|
|
60
|
-
},
|
|
61
|
-
toBeLessThanOrEqualAny(received, expected) {
|
|
62
|
-
return compare('toBeLessThanOrEqual', {
|
|
63
|
-
isNot: this.isNot,
|
|
64
|
-
promise: this.promise,
|
|
65
|
-
}, received, expected, '<=', () => received <= expected);
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
function compare(matcherName, options, received, expected, operator, fn) {
|
|
69
|
-
const pass = fn(received, expected);
|
|
70
|
-
const message = () => (0, jest_matcher_utils_1.matcherHint)(matcherName, undefined, undefined, options) +
|
|
71
|
-
'\n\n' +
|
|
72
|
-
`Expected:${options.isNot ? ' not' : ''} ${operator} ${(0, jest_matcher_utils_1.printExpected)(expected)}\n` +
|
|
73
|
-
`Received:${options.isNot ? ' ' : ''} ${(0, jest_matcher_utils_1.printReceived)(received)}`;
|
|
74
|
-
return { message, pass };
|
|
75
|
-
}
|
package/cjs/index.js
DELETED
package/cjs/package.json
DELETED
package/cjs/test-backend.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TestBackend = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const node_http_1 = require("node:http");
|
|
6
|
-
const path = tslib_1.__importStar(require("node:path"));
|
|
7
|
-
const client_1 = require("@opra/client");
|
|
8
|
-
const api_expect_js_1 = require("./api-expect/api-expect.js");
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* @class TestBackend
|
|
12
|
-
*/
|
|
13
|
-
class TestBackend extends client_1.FetchBackend {
|
|
14
|
-
constructor(app, options) {
|
|
15
|
-
super(options?.basePath
|
|
16
|
-
? path.posix.join('http://tempuri.org', options.basePath)
|
|
17
|
-
: 'http://tempuri.org', options);
|
|
18
|
-
this._server = app instanceof node_http_1.Server ? app : (0, node_http_1.createServer)(app);
|
|
19
|
-
}
|
|
20
|
-
send(req) {
|
|
21
|
-
return new Promise((resolve, reject) => {
|
|
22
|
-
const url = new URL(req.url);
|
|
23
|
-
// Set protocol to HTTP
|
|
24
|
-
url.protocol = 'http';
|
|
25
|
-
// Apply original host to request header
|
|
26
|
-
if (url.host !== 'opra.test' && req.headers.get('host') == null)
|
|
27
|
-
req.headers.set('host', url.host);
|
|
28
|
-
new Promise(subResolve => {
|
|
29
|
-
if (this._server.listening)
|
|
30
|
-
subResolve();
|
|
31
|
-
else
|
|
32
|
-
this._server.listen(0, '127.0.0.1', () => subResolve());
|
|
33
|
-
})
|
|
34
|
-
.then(() => {
|
|
35
|
-
const address = this._server.address();
|
|
36
|
-
url.host = '127.0.0.1';
|
|
37
|
-
url.port = address.port.toString();
|
|
38
|
-
return fetch(url.toString(), req);
|
|
39
|
-
})
|
|
40
|
-
.then(res => {
|
|
41
|
-
if (!this._server.listening)
|
|
42
|
-
return resolve(res);
|
|
43
|
-
this._server.once('close', () => resolve(res));
|
|
44
|
-
this._server.close();
|
|
45
|
-
this._server.unref();
|
|
46
|
-
})
|
|
47
|
-
.then()
|
|
48
|
-
.catch(error => {
|
|
49
|
-
if (!this._server.listening)
|
|
50
|
-
return reject(error);
|
|
51
|
-
this._server.once('close', () => reject(error));
|
|
52
|
-
this._server.close();
|
|
53
|
-
this._server.unref();
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
createResponse(init) {
|
|
58
|
-
const response = new client_1.HttpResponse(init);
|
|
59
|
-
response.expect = new api_expect_js_1.ApiExpect(response);
|
|
60
|
-
return response;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
exports.TestBackend = TestBackend;
|
package/cjs/test-client.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OpraTestClient = exports.kContext = void 0;
|
|
4
|
-
const client_1 = require("@opra/client");
|
|
5
|
-
const test_backend_js_1 = require("./test-backend.js");
|
|
6
|
-
exports.kContext = Symbol.for('kContext');
|
|
7
|
-
class OpraTestClient extends client_1.HttpClientBase {
|
|
8
|
-
constructor(app, options) {
|
|
9
|
-
super(new test_backend_js_1.TestBackend(app, options));
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
exports.OpraTestClient = OpraTestClient;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.objectMatches = objectMatches;
|
|
4
|
-
const expect_1 = require("expect");
|
|
5
|
-
function objectMatches(received, expected) {
|
|
6
|
-
_objectMatches(received, expected, '');
|
|
7
|
-
}
|
|
8
|
-
function _objectMatches(received, expected, path) {
|
|
9
|
-
if (typeof received !== typeof expected)
|
|
10
|
-
(0, expect_1.expect)(typeof received).toStrictEqual('object');
|
|
11
|
-
const keys = Object.keys(expected);
|
|
12
|
-
for (const k of keys) {
|
|
13
|
-
const rv = received[k];
|
|
14
|
-
const ev = expected[k];
|
|
15
|
-
if (ev instanceof RegExp) {
|
|
16
|
-
try {
|
|
17
|
-
(0, expect_1.expect)(rv).toMatch(ev);
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
throw new Error(`Property "${k}" does not match`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else if (ev && typeof ev === 'object') {
|
|
24
|
-
_objectMatches(rv, ev, path ? path + '.' + k : k);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
try {
|
|
28
|
-
(0, expect_1.expect)(rv).toEqual(ev);
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
throw new Error(`Property "${k}" does not match`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
package/esm/package.json
DELETED
package/types/index.d.cts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|