@locustjs/test 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 ironcodev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # About
2
+ This library provides a simple test runner.
3
+
4
+ # Install
5
+ ```
6
+ npm i @locustjs/test
7
+ ```
8
+
9
+ # Matchers
10
+ - `toBe()`
11
+ - `notToBe()`
12
+ - `toBeGt()`
13
+ - `toBeGte()`
14
+ - `toBeLt()`
15
+ - `toBeLte()`
16
+ - `toBeDefined()`
17
+ - `toBeUndefined()`
18
+ - `toBeNull()`
19
+ - `notToBeNull()`
20
+ - `toBeNullOrUndefined()`
21
+ - `notToBeNullOrUndefined()`
22
+ - `toThrow()`
23
+ - `toThrowAsync()`
24
+ - `notToThrow()`
25
+ - `notToThrowAsync()`
26
+
27
+ Example:
28
+ ```javascript
29
+ const tests = [
30
+ ['test 1', expect => expect(2 + 2).toBe(4)],
31
+ ['test 2', expect => expect(undefined).toBeUndefined()],
32
+ ['test 3', expect => expect(5).toBeGt(10)], // this test fails
33
+ ];
34
+
35
+ const runner = new TestRunner();
36
+
37
+ await runner.run(tests);
38
+
39
+ runner.report();
40
+ ```
package/index.cjs.js ADDED
@@ -0,0 +1,391 @@
1
+ import { isArray, isFunction } from '@locustjs/base';
2
+ import { Exception } from '@locustjs/exception';
3
+ class Expect {
4
+ constructor(value) {
5
+ this.value = value;
6
+ }
7
+ toBe(value) {
8
+ if (this.value === value) {} else {
9
+ throw new Exception({
10
+ message: `${this.value} is not equal to ${value}`,
11
+ code: 1000,
12
+ status: 'not-eq'
13
+ });
14
+ }
15
+ }
16
+ toBeGt(value) {
17
+ if (this.value <= value) {
18
+ throw new Exception({
19
+ message: `${this.value} is lower than or equal to ${value}`,
20
+ code: 1001,
21
+ status: 'lte'
22
+ });
23
+ }
24
+ }
25
+ toBeGte(value) {
26
+ if (this.value < value) {
27
+ throw new Exception({
28
+ message: `${this.value} is lower than to ${value}`,
29
+ code: 1002,
30
+ status: 'lt'
31
+ });
32
+ }
33
+ }
34
+ toBeLt(value) {
35
+ if (this.value >= value) {
36
+ throw new Exception({
37
+ message: `${this.value} is greater than or equal to ${value}`,
38
+ code: 1003,
39
+ status: 'gte'
40
+ });
41
+ }
42
+ }
43
+ toBeLte(value) {
44
+ if (this.value > value) {
45
+ throw new Exception({
46
+ message: `${this.value} is greater than ${value}`,
47
+ code: 1004,
48
+ status: 'gt'
49
+ });
50
+ }
51
+ }
52
+ notToBe(value) {
53
+ if (this.value === value) {
54
+ throw new Exception({
55
+ message: `${value} is equal to ${this.value}`,
56
+ code: 1005,
57
+ status: 'eq'
58
+ });
59
+ }
60
+ }
61
+ toBeDefined() {
62
+ if (this.value === undefined) {
63
+ throw new Exception({
64
+ message: `value is undefined`,
65
+ code: 1006,
66
+ status: 'undefined'
67
+ });
68
+ }
69
+ }
70
+ toBeUndefined() {
71
+ if (this.value !== undefined) {
72
+ throw new Exception({
73
+ message: `value is defined`,
74
+ code: 1007,
75
+ status: 'defined'
76
+ });
77
+ }
78
+ }
79
+ toBeNull() {
80
+ if (this.value !== null) {
81
+ throw new Exception({
82
+ message: `value is not null`,
83
+ code: 1008,
84
+ status: 'not-null'
85
+ });
86
+ }
87
+ }
88
+ notToBeNull() {
89
+ if (this.value === null) {
90
+ throw new Exception({
91
+ message: `value is null`,
92
+ code: 1009,
93
+ status: 'null'
94
+ });
95
+ }
96
+ }
97
+ toBeNullOrUndefined() {
98
+ if (this.value == null) {} else {
99
+ throw new Exception({
100
+ message: `value is not null/undefined`,
101
+ code: 1010,
102
+ status: 'not-null-or-undefined'
103
+ });
104
+ }
105
+ }
106
+ notToBeNullOrUndefined() {
107
+ if (this.value == null) {
108
+ throw new Exception({
109
+ message: `value is null/undefined`,
110
+ code: 1011,
111
+ status: 'null-or-undefined'
112
+ });
113
+ }
114
+ }
115
+ toThrow(fn) {
116
+ if (!isFunction(fn)) {
117
+ throw new Exception({
118
+ message: `given argument is not a function.`,
119
+ code: 1012,
120
+ status: 'no-func'
121
+ });
122
+ }
123
+ let ok = false;
124
+ try {
125
+ fn();
126
+ ok = true;
127
+ } catch (e) {}
128
+ if (ok) {
129
+ throw new Exception({
130
+ message: `given function ran without throwing any errors.`,
131
+ code: 1013,
132
+ status: 'ran-to-completion'
133
+ });
134
+ }
135
+ }
136
+ async toThrowAsync(fn) {
137
+ if (!isFunction(fn)) {
138
+ throw new Exception({
139
+ message: `given argument is not a function.`,
140
+ code: 1012,
141
+ status: 'no-func'
142
+ });
143
+ }
144
+ let ok = false;
145
+ try {
146
+ await fn();
147
+ ok = true;
148
+ } catch (e) {}
149
+ if (ok) {
150
+ throw new Exception({
151
+ message: `given function ran without throwing any errors.`,
152
+ code: 1013,
153
+ status: 'ran-to-completion'
154
+ });
155
+ }
156
+ }
157
+ notToThrow(fn) {
158
+ if (!isFunction(fn)) {
159
+ throw new Exception({
160
+ message: `given argument is not a function.`,
161
+ code: 1012,
162
+ status: 'no-func'
163
+ });
164
+ }
165
+ let ok = true;
166
+ let error;
167
+ try {
168
+ fn();
169
+ ok = false;
170
+ } catch (e) {
171
+ error = e;
172
+ }
173
+ if (ok) {
174
+ throw new Exception({
175
+ message: `given function threw an error.`,
176
+ code: 1014,
177
+ status: 'ran-to-error',
178
+ innerException: error
179
+ });
180
+ }
181
+ }
182
+ async notToThrowAsync(fn) {
183
+ if (!isFunction(fn)) {
184
+ throw new Exception({
185
+ message: `given argument is not a function.`,
186
+ code: 1012,
187
+ status: 'no-func'
188
+ });
189
+ }
190
+ let ok = true;
191
+ let error;
192
+ try {
193
+ await fn();
194
+ ok = false;
195
+ } catch (e) {
196
+ error = e;
197
+ }
198
+ if (ok) {
199
+ throw new Exception({
200
+ message: `given function threw an error.`,
201
+ code: 1014,
202
+ status: 'ran-to-error',
203
+ innerException: error
204
+ });
205
+ }
206
+ }
207
+ }
208
+ const expect = x => new Expect(x);
209
+ class Test {
210
+ constructor(name, fn) {
211
+ this.name = name;
212
+ this.fn = fn;
213
+ }
214
+ run() {
215
+ return new Promise(res => {
216
+ if (isFunction(this.fn)) {
217
+ try {
218
+ const start = new Date();
219
+ const _result = this.fn(expect);
220
+ if (_result && isFunction(_result.then)) {
221
+ _result.then(result => {
222
+ res({
223
+ success: true,
224
+ test: this.name,
225
+ result,
226
+ time: new Date() - start
227
+ });
228
+ }).catch(ex => {
229
+ res({
230
+ success: false,
231
+ test: this.name,
232
+ time: new Date() - start,
233
+ err: new Exception({
234
+ message: `test '${this.name}' failed.`,
235
+ code: 501,
236
+ status: 'failed',
237
+ innerException: ex
238
+ })
239
+ });
240
+ });
241
+ } else {
242
+ res({
243
+ success: true,
244
+ test: this.name,
245
+ time: new Date() - start,
246
+ result: _result
247
+ });
248
+ }
249
+ } catch (ex) {
250
+ res({
251
+ success: false,
252
+ test: this.name,
253
+ time: new Date() - start,
254
+ err: new Exception({
255
+ message: `test '${this.name}' failed.`,
256
+ code: 501,
257
+ status: 'failed',
258
+ innerException: ex
259
+ })
260
+ });
261
+ }
262
+ } else {
263
+ res({
264
+ success: false,
265
+ test: this.name,
266
+ time: new Date() - start,
267
+ err: new Exception({
268
+ message: `test '${this.name}' does not have a function to be called.`,
269
+ code: 500,
270
+ status: 'no-func'
271
+ })
272
+ });
273
+ }
274
+ });
275
+ }
276
+ }
277
+ const ConsoleColors = {
278
+ BackColor: {
279
+ Black: 40
280
+ },
281
+ ForeColor: {
282
+ Red: 31,
283
+ Green: 32,
284
+ White: 37,
285
+ Gray: 90
286
+ },
287
+ Modifier: {
288
+ Reset: "\x1b[0m"
289
+ }
290
+ };
291
+ class TestRunner {
292
+ constructor() {
293
+ this.passed = 0;
294
+ this.failed = 0;
295
+ this.results = [];
296
+ this.errors = [];
297
+ }
298
+ async _runSingle(test, onProgress, i) {
299
+ if (isFunction(onProgress)) {
300
+ try {
301
+ onProgress(i, test);
302
+ } catch (ex) {
303
+ this.errors.push({
304
+ err: new Exception({
305
+ message: `onProgress failed for test '${test.name} at index ${i}'.`,
306
+ code: 1500,
307
+ status: 'progress-failed'
308
+ })
309
+ });
310
+ }
311
+ }
312
+ const tr = await test.run();
313
+ this.results.push(tr);
314
+ if (tr.success) {
315
+ this.passed++;
316
+ } else {
317
+ this.failed++;
318
+ }
319
+ }
320
+ get result() {
321
+ return {
322
+ passed: this.passed,
323
+ failed: this.failed,
324
+ results: this.results,
325
+ errors: this.errors
326
+ };
327
+ }
328
+ run(tests, onProgress) {
329
+ this.passed = 0;
330
+ this.failed = 0;
331
+ this.results = [];
332
+ this.errors = [];
333
+ return new Promise(res => {
334
+ if (tests) {
335
+ if (tests instanceof Test) {
336
+ tests = [tests];
337
+ }
338
+ if (isArray(tests)) {
339
+ const _tests = tests.map(test => {
340
+ let _test = test;
341
+ if (isArray(test)) {
342
+ if (test.length == 2) {
343
+ _test = new Test(test[0], test[1]);
344
+ }
345
+ }
346
+ return _test;
347
+ }).filter(test => test instanceof Test).map((test, i) => this._runSingle(test, onProgress, i));
348
+ Promise.all(_tests).then(_ => res()).catch(ex => {
349
+ this.errors.push({
350
+ err: new Exception({
351
+ message: `not all tests succeeded. check errors.`,
352
+ code: 1503,
353
+ status: 'partial-finished',
354
+ innerException: ex
355
+ })
356
+ });
357
+ res();
358
+ });
359
+ } else {
360
+ this.errors.push({
361
+ err: new Exception({
362
+ message: `invalid tests. expected array or a single test.`,
363
+ code: 1502,
364
+ status: 'invalid-tests'
365
+ })
366
+ });
367
+ res();
368
+ }
369
+ } else {
370
+ this.errors.push({
371
+ err: new Exception({
372
+ message: `no tests given to be ran.`,
373
+ code: 1501,
374
+ status: 'no-tests'
375
+ })
376
+ });
377
+ res();
378
+ }
379
+ });
380
+ }
381
+ report() {
382
+ let time = 0;
383
+ for (let r of this.results) {
384
+ time += r.time;
385
+ }
386
+ const text = 'Finished.' + '\n' + (this.failed > 0 ? `\x1b[${ConsoleColors.ForeColor.Red}m ${this.failed} tests failed` : '0 tests failed' + ConsoleColors.Modifier.Reset) + ', ' + (this.passed > 0 ? `\x1b[${ConsoleColors.ForeColor.Green}m ${this.passed} tests passed` : '0 tests passed' + ConsoleColors.Modifier.Reset) + '\n' + `Tests: ${this.passed + this.failed}` + '\n' + `Time: ${time / 1000} sec` + '\n';
387
+ console.log(text);
388
+ }
389
+ }
390
+ export default TestRunner;
391
+ export { Test, Expect, expect };
package/index.esm.js ADDED
@@ -0,0 +1,296 @@
1
+ import { isArray, isFunction } from '@locustjs/base';
2
+ import { Exception } from '@locustjs/exception';
3
+
4
+ class Expect {
5
+ constructor(value) {
6
+ this.value = value
7
+ }
8
+ toBe(value) {
9
+ if (this.value === value) {
10
+ } else {
11
+ throw new Exception({ message: `${this.value} is not equal to ${value}`, code: 1000, status: 'not-eq' })
12
+ }
13
+ }
14
+ toBeGt(value) {
15
+ if (this.value <= value) {
16
+ throw new Exception({ message: `${this.value} is lower than or equal to ${value}`, code: 1001, status: 'lte' })
17
+ }
18
+ }
19
+ toBeGte(value) {
20
+ if (this.value < value) {
21
+ throw new Exception({ message: `${this.value} is lower than to ${value}`, code: 1002, status: 'lt' })
22
+ }
23
+ }
24
+ toBeLt(value) {
25
+ if (this.value >= value) {
26
+ throw new Exception({ message: `${this.value} is greater than or equal to ${value}`, code: 1003, status: 'gte' })
27
+ }
28
+ }
29
+ toBeLte(value) {
30
+ if (this.value > value) {
31
+ throw new Exception({ message: `${this.value} is greater than ${value}`, code: 1004, status: 'gt' })
32
+ }
33
+ }
34
+ notToBe(value) {
35
+ if (this.value === value) {
36
+ throw new Exception({ message: `${value} is equal to ${this.value}`, code: 1005, status: 'eq' })
37
+ }
38
+ }
39
+ toBeDefined() {
40
+ if (this.value === undefined) {
41
+ throw new Exception({ message: `value is undefined`, code: 1006, status: 'undefined' })
42
+ }
43
+ }
44
+ toBeUndefined() {
45
+ if (this.value !== undefined) {
46
+ throw new Exception({ message: `value is defined`, code: 1007, status: 'defined' })
47
+ }
48
+ }
49
+ toBeNull() {
50
+ if (this.value !== null) {
51
+ throw new Exception({ message: `value is not null`, code: 1008, status: 'not-null' })
52
+ }
53
+ }
54
+ notToBeNull() {
55
+ if (this.value === null) {
56
+ throw new Exception({ message: `value is null`, code: 1009, status: 'null' })
57
+ }
58
+ }
59
+ toBeNullOrUndefined() {
60
+ if (this.value == null) {
61
+ } else {
62
+ throw new Exception({ message: `value is not null/undefined`, code: 1010, status: 'not-null-or-undefined' })
63
+ }
64
+ }
65
+ notToBeNullOrUndefined() {
66
+ if (this.value == null) {
67
+ throw new Exception({ message: `value is null/undefined`, code: 1011, status: 'null-or-undefined' })
68
+ }
69
+ }
70
+ toThrow(fn) {
71
+ if (!isFunction(fn)) {
72
+ throw new Exception({ message: `given argument is not a function.`, code: 1012, status: 'no-func' })
73
+ }
74
+
75
+ let ok = false;
76
+
77
+ try {
78
+ fn();
79
+
80
+ ok = true;
81
+ } catch (e) { }
82
+
83
+ if (ok) {
84
+ throw new Exception({ message: `given function ran without throwing any errors.`, code: 1013, status: 'ran-to-completion' })
85
+ }
86
+ }
87
+ async toThrowAsync(fn) {
88
+ if (!isFunction(fn)) {
89
+ throw new Exception({ message: `given argument is not a function.`, code: 1012, status: 'no-func' })
90
+ }
91
+
92
+ let ok = false;
93
+
94
+ try {
95
+ await fn();
96
+
97
+ ok = true;
98
+ } catch (e) { }
99
+
100
+ if (ok) {
101
+ throw new Exception({ message: `given function ran without throwing any errors.`, code: 1013, status: 'ran-to-completion' })
102
+ }
103
+ }
104
+ notToThrow(fn) {
105
+ if (!isFunction(fn)) {
106
+ throw new Exception({ message: `given argument is not a function.`, code: 1012, status: 'no-func' })
107
+ }
108
+
109
+ let ok = true;
110
+ let error;
111
+
112
+ try {
113
+ fn();
114
+
115
+ ok = false;
116
+ } catch (e) { error = e; }
117
+
118
+ if (ok) {
119
+ throw new Exception({ message: `given function threw an error.`, code: 1014, status: 'ran-to-error', innerException: error })
120
+ }
121
+ }
122
+ async notToThrowAsync(fn) {
123
+ if (!isFunction(fn)) {
124
+ throw new Exception({ message: `given argument is not a function.`, code: 1012, status: 'no-func' })
125
+ }
126
+
127
+ let ok = true;
128
+ let error;
129
+
130
+ try {
131
+ await fn();
132
+
133
+ ok = false;
134
+ } catch (e) { error = e; }
135
+
136
+ if (ok) {
137
+ throw new Exception({ message: `given function threw an error.`, code: 1014, status: 'ran-to-error', innerException: error })
138
+ }
139
+ }
140
+ }
141
+
142
+ const expect = (x) => new Expect(x);
143
+
144
+ class Test {
145
+ constructor(name, fn) {
146
+ this.name = name;
147
+ this.fn = fn;
148
+ }
149
+ run() {
150
+ return new Promise(res => {
151
+ if (isFunction(this.fn)) {
152
+ try {
153
+ const start = new Date();
154
+ const _result = this.fn(expect);
155
+
156
+ if (_result && isFunction(_result.then)) {
157
+ _result.then(result => {
158
+ res({ success: true, test: this.name, result, time: new Date() - start });
159
+ }).catch(ex => {
160
+ res({ success: false, test: this.name, time: new Date() - start, err: new Exception({ message: `test '${this.name}' failed.`, code: 501, status: 'failed', innerException: ex }) })
161
+ });
162
+ } else {
163
+ res({ success: true, test: this.name, time: new Date() - start, result: _result });
164
+ }
165
+ } catch (ex) {
166
+ res({ success: false, test: this.name, time: new Date() - start, err: new Exception({ message: `test '${this.name}' failed.`, code: 501, status: 'failed', innerException: ex }) })
167
+ }
168
+ } else {
169
+ res({ success: false, test: this.name, time: new Date() - start, err: new Exception({ message: `test '${this.name}' does not have a function to be called.`, code: 500, status: 'no-func' }) })
170
+ }
171
+ });
172
+ }
173
+ }
174
+
175
+ const ConsoleColors = {
176
+ BackColor: {
177
+ Black: 40,
178
+ },
179
+ ForeColor: {
180
+ Red: 31,
181
+ Green: 32,
182
+ White: 37,
183
+ Gray: 90,
184
+ },
185
+ Modifier: {
186
+ Reset: "\x1b[0m",
187
+ },
188
+ };
189
+
190
+ class TestRunner {
191
+ constructor() {
192
+ this.passed = 0;
193
+ this.failed = 0;
194
+ this.results = []
195
+ this.errors = []
196
+ }
197
+ async _runSingle(test, onProgress, i) {
198
+ if (isFunction(onProgress)) {
199
+ try {
200
+ onProgress(i, test);
201
+ } catch (ex) {
202
+ this.errors.push({ err: new Exception({ message: `onProgress failed for test '${test.name} at index ${i}'.`, code: 1500, status: 'progress-failed' }) })
203
+ }
204
+ }
205
+
206
+ const tr = await test.run();
207
+
208
+ this.results.push(tr);
209
+
210
+ if (tr.success) {
211
+ this.passed++;
212
+ } else {
213
+ this.failed++;
214
+ }
215
+ }
216
+ get result() {
217
+ return {
218
+ passed: this.passed,
219
+ failed: this.failed,
220
+ results: this.results,
221
+ errors: this.errors
222
+ }
223
+ }
224
+ run(tests, onProgress) {
225
+ this.passed = 0;
226
+ this.failed = 0;
227
+ this.results = [];
228
+ this.errors = [];
229
+
230
+ return new Promise(res => {
231
+ if (tests) {
232
+ if (tests instanceof Test) {
233
+ tests = [tests]
234
+ }
235
+
236
+ if (isArray(tests)) {
237
+ const _tests = tests
238
+ .map(test => {
239
+ let _test = test;
240
+
241
+ if (isArray(test)) {
242
+ if (test.length == 2) {
243
+ _test = new Test(test[0], test[1]);
244
+ }
245
+ }
246
+
247
+ return _test;
248
+ })
249
+ .filter(test => (test instanceof Test))
250
+ .map((test, i) => this._runSingle(test, onProgress, i));
251
+
252
+ Promise.all(_tests).then(_ => res()).catch(ex => {
253
+ this.errors.push({ err: new Exception({ message: `not all tests succeeded. check errors.`, code: 1503, status: 'partial-finished', innerException: ex }) });
254
+
255
+ res();
256
+ });
257
+ } else {
258
+ this.errors.push({ err: new Exception({ message: `invalid tests. expected array or a single test.`, code: 1502, status: 'invalid-tests' }) });
259
+
260
+ res();
261
+ }
262
+ } else {
263
+ this.errors.push({ err: new Exception({ message: `no tests given to be ran.`, code: 1501, status: 'no-tests' }) });
264
+
265
+ res();
266
+ }
267
+ })
268
+ }
269
+ report() {
270
+ let time = 0;
271
+
272
+ for (let r of this.results) {
273
+ time += r.time;
274
+ }
275
+
276
+ const text = 'Finished.' +
277
+ '\n' +
278
+ (this.failed > 0 ? `\x1b[${ConsoleColors.ForeColor.Red}m ${this.failed} tests failed` : '0 tests failed' + ConsoleColors.Modifier.Reset) +
279
+ ', ' +
280
+ (this.passed > 0 ? `\x1b[${ConsoleColors.ForeColor.Green}m ${this.passed} tests passed` : '0 tests passed' + ConsoleColors.Modifier.Reset) +
281
+ '\n' +
282
+ `Tests: ${this.passed + this.failed}` +
283
+ '\n' +
284
+ `Time: ${time / 1000} sec` +
285
+ '\n';
286
+
287
+ console.log(text);
288
+ }
289
+ }
290
+
291
+ export default TestRunner;
292
+ export {
293
+ Test,
294
+ Expect,
295
+ expect
296
+ }
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@locustjs/test",
3
+ "version": "1.0.0",
4
+ "description": "This library provides a simple test runner.",
5
+ "main": "index.cjs.js",
6
+ "module": "index.esm.js",
7
+ "scripts": {
8
+ "build": "babel index.esm.js -o index.cjs.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/ironcodev/locustjs-test.git"
13
+ },
14
+ "keywords": [
15
+ "locustjs",
16
+ "test runner"
17
+ ],
18
+ "author": "Iron Code",
19
+ "license": "MIT",
20
+ "bugs": {
21
+ "url": "https://github.com/ironcodev/locustjs-test/issues"
22
+ },
23
+ "homepage": "https://github.com/ironcodev/locustjs-test#readme",
24
+ "dependencies": {
25
+ "@locustjs/base": "^2.1.0",
26
+ "@locustjs/exception": "^2.0.1"
27
+ },
28
+ "devDependencies": {
29
+ "@babel/cli": "^7.22.6",
30
+ "@babel/core": "^7.22.8"
31
+ }
32
+ }