@ehuelsmann/jest-openapi 0.15.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/README.md +364 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/matchers/toSatisfyApiSpec.d.ts +3 -0
- package/dist/matchers/toSatisfyApiSpec.d.ts.map +1 -0
- package/dist/matchers/toSatisfyApiSpec.js +81 -0
- package/dist/matchers/toSatisfyApiSpec.js.map +1 -0
- package/dist/matchers/toSatisfySchemaInApiSpec.d.ts +3 -0
- package/dist/matchers/toSatisfySchemaInApiSpec.d.ts.map +1 -0
- package/dist/matchers/toSatisfySchemaInApiSpec.js +36 -0
- package/dist/matchers/toSatisfySchemaInApiSpec.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +9 -0
- package/dist/utils.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# @ehuelsmann/jest-openapi
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ehuelsmann/jest-openapi)
|
|
4
|
+
[](https://www.npmjs.com/package/@ehuelsmann/jest-openapi)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://codecov.io/gh/openapi-library/OpenAPIValidators)
|
|
8
|
+
[](https://github.com/openapi-library/OpenAPIValidators/blob/master/packages/jest-openapi/src/index.ts)
|
|
9
|
+
[](https://github.com/openapi-library/OpenAPIValidators/blob/master/CONTRIBUTING.md)
|
|
10
|
+
|
|
11
|
+
Additional Jest matchers for asserting that HTTP responses satisfy an OpenAPI spec.
|
|
12
|
+
|
|
13
|
+
## Problem 😕
|
|
14
|
+
|
|
15
|
+
If your server's behaviour doesn't match your API documentation, then you need to correct your server, your documentation, or both. The sooner you know the better.
|
|
16
|
+
|
|
17
|
+
## Solution 😄
|
|
18
|
+
|
|
19
|
+
This plugin lets you automatically test whether your server's behaviour and documentation match. It adds Jest matchers that support the [OpenAPI standard](https://swagger.io/docs/specification/about/) for documenting REST APIs. In your JavaScript tests, you can simply assert [`expect(responseObject).toSatisfyApiSpec()`](#in-api-tests-validate-the-status-and-body-of-http-responses-against-your-openapi-spec)
|
|
20
|
+
|
|
21
|
+
Features:
|
|
22
|
+
|
|
23
|
+
- Validates the status and body of HTTP responses against your OpenAPI spec [(see example)](#in-api-tests-validate-the-status-and-body-of-http-responses-against-your-openapi-spec)
|
|
24
|
+
- Validates objects against schemas defined in your OpenAPI spec [(see example)](#in-unit-tests-validate-objects-against-schemas-defined-in-your-OpenAPI-spec)
|
|
25
|
+
- Load your OpenAPI spec just once in your tests (load from a filepath or object)
|
|
26
|
+
- Supports OpenAPI [2](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) and [3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md)
|
|
27
|
+
- Supports OpenAPI specs in YAML and JSON formats
|
|
28
|
+
- Supports `$ref` in response definitions (i.e. `$ref: '#/definitions/ComponentType/ComponentName'`)
|
|
29
|
+
- Informs you if your OpenAPI spec is invalid
|
|
30
|
+
- Supports responses from `axios`, `request-promise`, `supertest`, `superagent`, and `chai-http`
|
|
31
|
+
- Use in [Jest](#usage), or use our [sister package](https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/chai-openapi-response-validator#readme) for Mocha and other test runners that support Chai
|
|
32
|
+
|
|
33
|
+
## Contributing ✨
|
|
34
|
+
|
|
35
|
+
If you've come here to help contribute - thanks! Take a look at the [contributing](https://github.com/openapi-library/OpenAPIValidators/blob/master/CONTRIBUTING.md) docs to get started.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
[npm](http://npmjs.org)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install --save-dev @ehuelsmann/jest-openapi
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
[yarn](https://yarnpkg.com/)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
yarn add --dev @ehuelsmann/jest-openapi
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Importing
|
|
52
|
+
|
|
53
|
+
ES6 / TypeScript
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import jestOpenAPI from '@ehuelsmann/jest-openapi';
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
CommonJS / JavaScript
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const jestOpenAPI = require('@ehuelsmann/jest-openapi').default;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
### In API tests, validate the status and body of HTTP responses against your OpenAPI spec:
|
|
68
|
+
|
|
69
|
+
#### 1. Write a test:
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
// Import this plugin
|
|
73
|
+
import jestOpenAPI from '@ehuelsmann/jest-openapi';
|
|
74
|
+
|
|
75
|
+
// Load an OpenAPI file (YAML or JSON) into this plugin
|
|
76
|
+
jestOpenAPI('path/to/openapi.yml');
|
|
77
|
+
|
|
78
|
+
// Write your test
|
|
79
|
+
describe('GET /example/endpoint', () => {
|
|
80
|
+
it('should satisfy OpenAPI spec', async () => {
|
|
81
|
+
// Get an HTTP response from your server (e.g. using axios)
|
|
82
|
+
const res = await axios.get('http://localhost:3000/example/endpoint');
|
|
83
|
+
|
|
84
|
+
expect(res.status).toEqual(200);
|
|
85
|
+
|
|
86
|
+
// Assert that the HTTP response satisfies the OpenAPI spec
|
|
87
|
+
expect(res).toSatisfyApiSpec();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### 2. Write an OpenAPI Spec (and save to `path/to/openapi.yml`):
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
openapi: 3.0.0
|
|
96
|
+
info:
|
|
97
|
+
title: Example API
|
|
98
|
+
version: 1.0.0
|
|
99
|
+
paths:
|
|
100
|
+
/example:
|
|
101
|
+
get:
|
|
102
|
+
responses:
|
|
103
|
+
200:
|
|
104
|
+
description: Response body should be an object with fields 'stringProperty' and 'integerProperty'
|
|
105
|
+
content:
|
|
106
|
+
application/json:
|
|
107
|
+
schema:
|
|
108
|
+
type: object
|
|
109
|
+
required:
|
|
110
|
+
- stringProperty
|
|
111
|
+
- integerProperty
|
|
112
|
+
properties:
|
|
113
|
+
stringProperty:
|
|
114
|
+
type: string
|
|
115
|
+
integerProperty:
|
|
116
|
+
type: integer
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### 3. Run your test to validate your server's response against your OpenAPI spec:
|
|
120
|
+
|
|
121
|
+
##### The assertion passes if the response status and body satisfy `openapi.yml`:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
// Response includes:
|
|
125
|
+
{
|
|
126
|
+
status: 200,
|
|
127
|
+
body: {
|
|
128
|
+
stringProperty: 'string',
|
|
129
|
+
integerProperty: 123,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
##### The assertion fails if the response body is invalid:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Response includes:
|
|
138
|
+
{
|
|
139
|
+
status: 200,
|
|
140
|
+
body: {
|
|
141
|
+
stringProperty: 'string',
|
|
142
|
+
integerProperty: 'invalid (should be an integer)',
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
###### Output from test failure:
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
expect(received).toSatisfyApiSpec() // Matches 'received' to a response defined in your API spec, then validates 'received' against it
|
|
151
|
+
|
|
152
|
+
expected received to satisfy the '200' response defined for endpoint 'GET /example/endpoint' in your API spec
|
|
153
|
+
received did not satisfy it because: integerProperty should be integer
|
|
154
|
+
|
|
155
|
+
received contained: {
|
|
156
|
+
body: {
|
|
157
|
+
stringProperty: 'string',
|
|
158
|
+
integerProperty: 'invalid (should be an integer)'
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
The '200' response defined for endpoint 'GET /example/endpoint' in API spec: {
|
|
164
|
+
'200': {
|
|
165
|
+
description: 'Response body should be a string',
|
|
166
|
+
content: {
|
|
167
|
+
'application/json': {
|
|
168
|
+
schema: {
|
|
169
|
+
type: 'string'
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### In unit tests, validate objects against schemas defined in your OpenAPI spec:
|
|
178
|
+
|
|
179
|
+
#### 1. Write a test:
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
// Import this plugin and the function you want to test
|
|
183
|
+
import jestOpenAPI from '@ehuelsmann/jest-openapi';
|
|
184
|
+
import { functionToTest } from 'path/to/your/code';
|
|
185
|
+
|
|
186
|
+
// Load an OpenAPI file (YAML or JSON) into this plugin
|
|
187
|
+
jestOpenAPI('path/to/openapi.yml');
|
|
188
|
+
|
|
189
|
+
// Write your test
|
|
190
|
+
describe('functionToTest()', () => {
|
|
191
|
+
it('should satisfy OpenAPI spec', async () => {
|
|
192
|
+
// Assert that the function returns a value satisfying a schema defined in your OpenAPI spec
|
|
193
|
+
expect(functionToTest()).toSatisfySchemaInApiSpec('ExampleSchemaObject');
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### 2. Write an OpenAPI Spec (and save to `path/to/openapi.yml`):
|
|
199
|
+
|
|
200
|
+
```yaml
|
|
201
|
+
openapi: 3.0.0
|
|
202
|
+
info:
|
|
203
|
+
title: Example API
|
|
204
|
+
version: 1.0.0
|
|
205
|
+
paths:
|
|
206
|
+
/example:
|
|
207
|
+
get:
|
|
208
|
+
responses:
|
|
209
|
+
200:
|
|
210
|
+
description: Response body should be an ExampleSchemaObject
|
|
211
|
+
content:
|
|
212
|
+
application/json:
|
|
213
|
+
schema:
|
|
214
|
+
$ref: '#/components/schemas/ExampleSchemaObject'
|
|
215
|
+
components:
|
|
216
|
+
schemas:
|
|
217
|
+
ExampleSchemaObject:
|
|
218
|
+
type: object
|
|
219
|
+
required:
|
|
220
|
+
- stringProperty
|
|
221
|
+
- integerProperty
|
|
222
|
+
properties:
|
|
223
|
+
stringProperty:
|
|
224
|
+
type: string
|
|
225
|
+
integerProperty:
|
|
226
|
+
type: integer
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### 3. Run your test to validate your object against your OpenAPI spec:
|
|
230
|
+
|
|
231
|
+
##### The assertion passes if the object satisfies the schema `ExampleSchemaObject`:
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// object includes:
|
|
235
|
+
{
|
|
236
|
+
stringProperty: 'string',
|
|
237
|
+
integerProperty: 123,
|
|
238
|
+
};
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
##### The assertion fails if the object does not satisfy the schema `ExampleSchemaObject`:
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
// object includes:
|
|
245
|
+
{
|
|
246
|
+
stringProperty: 123,
|
|
247
|
+
integerProperty: 123,
|
|
248
|
+
};
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
###### Output from test failure:
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
expect(received).not.toSatisfySchemaInApiSpec(schemaName) // Matches 'received' to a schema defined in your API spec, then validates 'received' against it
|
|
255
|
+
|
|
256
|
+
expected received to satisfy the 'StringSchema' schema defined in your API spec
|
|
257
|
+
object did not satisfy it because: stringProperty should be string
|
|
258
|
+
|
|
259
|
+
object was: {
|
|
260
|
+
{
|
|
261
|
+
stringProperty: 123,
|
|
262
|
+
integerProperty: 123
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
The 'ExampleSchemaObject' schema in API spec: {
|
|
268
|
+
type: 'object',
|
|
269
|
+
required: [
|
|
270
|
+
'stringProperty'
|
|
271
|
+
'integerProperty'
|
|
272
|
+
],
|
|
273
|
+
properties: {
|
|
274
|
+
stringProperty: {
|
|
275
|
+
type: 'string'
|
|
276
|
+
},
|
|
277
|
+
integerProperty: {
|
|
278
|
+
type: 'integer'
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Loading your OpenAPI spec (3 different ways):
|
|
285
|
+
|
|
286
|
+
#### 1. From an absolute filepath ([see above](#usage))
|
|
287
|
+
|
|
288
|
+
#### 2. From an object:
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
// Import this plugin
|
|
292
|
+
import jestOpenAPI from '@ehuelsmann/jest-openapi';
|
|
293
|
+
|
|
294
|
+
// Get an object representing your OpenAPI spec
|
|
295
|
+
const openApiSpec = {
|
|
296
|
+
openapi: '3.0.0',
|
|
297
|
+
info: {
|
|
298
|
+
title: 'Example API',
|
|
299
|
+
version: '0.1.0',
|
|
300
|
+
},
|
|
301
|
+
paths: {
|
|
302
|
+
'/example/endpoint': {
|
|
303
|
+
get: {
|
|
304
|
+
responses: {
|
|
305
|
+
200: {
|
|
306
|
+
description: 'Response body should be a string',
|
|
307
|
+
content: {
|
|
308
|
+
'application/json': {
|
|
309
|
+
schema: {
|
|
310
|
+
type: 'string',
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// Load that OpenAPI object into this plugin
|
|
322
|
+
jestOpenAPI(openApiSpec);
|
|
323
|
+
|
|
324
|
+
// Write your test
|
|
325
|
+
describe('GET /example/endpoint', () => {
|
|
326
|
+
it('should satisfy OpenAPI spec', async () => {
|
|
327
|
+
// Get an HTTP response from your server (e.g. using axios)
|
|
328
|
+
const res = await axios.get('http://localhost:3000/example/endpoint');
|
|
329
|
+
|
|
330
|
+
expect(res.status).toEqual(200);
|
|
331
|
+
|
|
332
|
+
// Assert that the HTTP response satisfies the OpenAPI spec
|
|
333
|
+
expect(res).toSatisfyApiSpec();
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### 3. From a web endpoint:
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
// Import this plugin and an HTTP client (e.g. axios)
|
|
342
|
+
import jestOpenAPI from '@ehuelsmann/jest-openapi';
|
|
343
|
+
import axios from 'axios';
|
|
344
|
+
|
|
345
|
+
// Write your test
|
|
346
|
+
describe('GET /example/endpoint', () => {
|
|
347
|
+
// Load your OpenAPI spec from a web endpoint
|
|
348
|
+
beforeAll(async () => {
|
|
349
|
+
const response = await axios.get('url/to/openapi/spec');
|
|
350
|
+
const openApiSpec = response.data; // e.g. { openapi: '3.0.0', ... };
|
|
351
|
+
jestOpenAPI(openApiSpec);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('should satisfy OpenAPI spec', async () => {
|
|
355
|
+
// Get an HTTP response from your server
|
|
356
|
+
const res = await axios.get('http://localhost:3000/example/endpoint');
|
|
357
|
+
|
|
358
|
+
expect(res.status).toEqual(200);
|
|
359
|
+
|
|
360
|
+
// Assert that the HTTP response satisfies the OpenAPI spec
|
|
361
|
+
expect(res).toSatisfyApiSpec();
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OpenAPISpecObject } from '@ehuelsmann/openapi-validator';
|
|
2
|
+
declare global {
|
|
3
|
+
namespace jest {
|
|
4
|
+
interface Matchers<R> {
|
|
5
|
+
/**
|
|
6
|
+
* Check the HTTP response object satisfies a response defined in your OpenAPI spec.
|
|
7
|
+
* [See usage example](https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/jest-openapi#in-api-tests-validate-the-status-and-body-of-http-responses-against-your-openapi-spec)
|
|
8
|
+
*/
|
|
9
|
+
toSatisfyApiSpec(): R;
|
|
10
|
+
/**
|
|
11
|
+
* Check the object satisfies a schema defined in your OpenAPI spec.
|
|
12
|
+
* [See usage example](https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/jest-openapi#in-unit-tests-validate-objects-against-schemas-defined-in-your-openapi-spec)
|
|
13
|
+
*/
|
|
14
|
+
toSatisfySchemaInApiSpec(schemaName: string): R;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export default function (filepathOrObject: string | OpenAPISpecObject): void;
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAI/E,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,IAAI,CAAC;QACb,UAAU,QAAQ,CAAC,CAAC;YAClB;;;eAGG;YACH,gBAAgB,IAAI,CAAC,CAAC;YACtB;;;eAGG;YACH,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC;SACjD;KACF;CACF;AAED,MAAM,CAAC,OAAO,WAAW,gBAAgB,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAiC3E"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const openapi_validator_1 = require("@ehuelsmann/openapi-validator");
|
|
8
|
+
const toSatisfyApiSpec_1 = __importDefault(require("./matchers/toSatisfyApiSpec"));
|
|
9
|
+
const toSatisfySchemaInApiSpec_1 = __importDefault(require("./matchers/toSatisfySchemaInApiSpec"));
|
|
10
|
+
function default_1(filepathOrObject) {
|
|
11
|
+
const openApiSpec = (0, openapi_validator_1.makeApiSpec)(filepathOrObject);
|
|
12
|
+
const jestMatchers = {
|
|
13
|
+
toSatisfyApiSpec(received) {
|
|
14
|
+
return toSatisfyApiSpec_1.default.call(this, received, openApiSpec);
|
|
15
|
+
},
|
|
16
|
+
toSatisfySchemaInApiSpec(received, schemaName) {
|
|
17
|
+
return toSatisfySchemaInApiSpec_1.default.call(this, received, schemaName, openApiSpec);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const jestExpect = global.expect;
|
|
21
|
+
/* istanbul ignore next */
|
|
22
|
+
if (jestExpect !== undefined) {
|
|
23
|
+
jestExpect.extend(jestMatchers);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
27
|
+
console.error([
|
|
28
|
+
"Unable to find Jest's global expect.",
|
|
29
|
+
'Please check you have configured jest-openapi correctly.',
|
|
30
|
+
'See https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/jest-openapi#usage for help.',
|
|
31
|
+
].join('\n'));
|
|
32
|
+
}
|
|
33
|
+
/* istanbul ignore next */
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAsBA,4BAiCC;AAvDD,qEAA+E;AAC/E,mFAA2D;AAC3D,mGAA2E;AAoB3E,mBAAyB,gBAA4C;IACnE,MAAM,WAAW,GAAG,IAAA,+BAAW,EAAC,gBAAgB,CAAC,CAAC;IAElD,MAAM,YAAY,GAAyB;QACzC,gBAAgB,CAAC,QAAiB;YAChC,OAAO,0BAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC5D,CAAC;QACD,wBAAwB,CAAC,QAAiB,EAAE,UAAkB;YAC5D,OAAO,kCAAwB,CAAC,IAAI,CAClC,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,WAAW,CACZ,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,MAAM,UAAU,GAAI,MAAmC,CAAC,MAAM,CAAC;IAE/D,0BAA0B;IAC1B,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,sCAAsC;QACtC,OAAO,CAAC,KAAK,CACX;YACE,sCAAsC;YACtC,0DAA0D;YAC1D,4GAA4G;SAC7G,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;IACD,0BAA0B;AAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfyApiSpec.d.ts","sourceRoot":"","sources":["../../src/matchers/toSatisfyApiSpec.ts"],"names":[],"mappings":"AAMA,OAAO,EAML,WAAW,EAGZ,MAAM,+BAA+B,CAAC;AAGvC,MAAM,CAAC,OAAO,WACZ,IAAI,EAAE,IAAI,CAAC,cAAc,EACzB,QAAQ,EAAE,OAAO,EACjB,WAAW,EAAE,WAAW,GACvB,IAAI,CAAC,mBAAmB,CAqC1B"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const jest_matcher_utils_1 = require("jest-matcher-utils");
|
|
5
|
+
const openapi_validator_1 = require("@ehuelsmann/openapi-validator");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function default_1(received, openApiSpec) {
|
|
8
|
+
const actualResponse = (0, openapi_validator_1.makeResponse)(received);
|
|
9
|
+
const validationError = openApiSpec.validateResponse(actualResponse);
|
|
10
|
+
const pass = !validationError;
|
|
11
|
+
const matcherHintOptions = {
|
|
12
|
+
comment: "Matches 'received' to a response defined in your API spec, then validates 'received' against it",
|
|
13
|
+
...(this.isNot !== undefined && { isNot: this.isNot }),
|
|
14
|
+
...(this.promise !== undefined && { promise: this.promise }),
|
|
15
|
+
};
|
|
16
|
+
const hint = (0, jest_matcher_utils_1.matcherHint)('toSatisfyApiSpec', undefined, '', matcherHintOptions);
|
|
17
|
+
const message = pass
|
|
18
|
+
? () => getExpectReceivedNotToSatisfyApiSpecMsg(actualResponse, openApiSpec, hint)
|
|
19
|
+
: () => getExpectReceivedToSatisfyApiSpecMsg(actualResponse, openApiSpec, validationError, hint);
|
|
20
|
+
return {
|
|
21
|
+
pass,
|
|
22
|
+
message,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function getExpectReceivedToSatisfyApiSpecMsg(actualResponse, openApiSpec, validationError, hint) {
|
|
26
|
+
const { status, req } = actualResponse;
|
|
27
|
+
const { method, path: requestPath } = req;
|
|
28
|
+
const unmatchedEndpoint = `${method} ${requestPath}`;
|
|
29
|
+
if (validationError.code === openapi_validator_1.ErrorCode.ServerNotFound) {
|
|
30
|
+
// prettier-ignore
|
|
31
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy a '${status}' response defined for endpoint '${unmatchedEndpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} had request path ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(requestPath)}, but your API spec has no matching servers`, `Servers found in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)(openApiSpec.getServerUrls().join(', '))}`);
|
|
32
|
+
}
|
|
33
|
+
if (validationError.code === openapi_validator_1.ErrorCode.BasePathNotFound) {
|
|
34
|
+
// prettier-ignore
|
|
35
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy a '${status}' response defined for endpoint '${unmatchedEndpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} had request path ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(requestPath)}, but your API spec has basePath ${(0, jest_matcher_utils_1.EXPECTED_COLOR)(openApiSpec.spec.basePath)}`);
|
|
36
|
+
}
|
|
37
|
+
if (validationError.code === openapi_validator_1.ErrorCode.PathNotFound) {
|
|
38
|
+
// prettier-ignore
|
|
39
|
+
const pathNotFoundErrorMessage = (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy a '${status}' response defined for endpoint '${unmatchedEndpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} had request path ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(requestPath)}, but your API spec has no matching path`, `Paths found in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)(openApiSpec.paths().join(', '))}`);
|
|
40
|
+
if ('didUserDefineBasePath' in openApiSpec &&
|
|
41
|
+
openApiSpec.didUserDefineBasePath) {
|
|
42
|
+
// prettier-ignore
|
|
43
|
+
return (0, utils_1.joinWithNewLines)(pathNotFoundErrorMessage, `'${requestPath}' matches basePath \`${openApiSpec.spec.basePath}\` but no <basePath/endpointPath> combinations`);
|
|
44
|
+
}
|
|
45
|
+
if ('didUserDefineServers' in openApiSpec &&
|
|
46
|
+
openApiSpec.didUserDefineServers) {
|
|
47
|
+
return (0, utils_1.joinWithNewLines)(pathNotFoundErrorMessage, `'${requestPath}' matches servers ${(0, utils_1.stringify)(openApiSpec.getMatchingServerUrls(requestPath))} but no <server/endpointPath> combinations`);
|
|
48
|
+
}
|
|
49
|
+
return pathNotFoundErrorMessage;
|
|
50
|
+
}
|
|
51
|
+
const path = openApiSpec.findOpenApiPathMatchingRequest(req);
|
|
52
|
+
const endpoint = `${method} ${path}`;
|
|
53
|
+
if (validationError.code === openapi_validator_1.ErrorCode.MethodNotFound) {
|
|
54
|
+
const expectedPathItem = openApiSpec.findExpectedPathItem(req);
|
|
55
|
+
const expectedRequestOperations = Object.keys(expectedPathItem)
|
|
56
|
+
.map((operation) => operation.toUpperCase())
|
|
57
|
+
.join(', ');
|
|
58
|
+
// prettier-ignore
|
|
59
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy a '${status}' response defined for endpoint '${endpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} had request method ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(method)}, but your API spec has no ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(method)} operation defined for path '${path}'`, `Request operations found for path '${path}' in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)(expectedRequestOperations)}`);
|
|
60
|
+
}
|
|
61
|
+
if (validationError.code === openapi_validator_1.ErrorCode.StatusNotFound) {
|
|
62
|
+
const expectedResponseOperation =
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
64
|
+
openApiSpec.findExpectedResponseOperation(req);
|
|
65
|
+
const expectedResponseStatuses = Object.keys(expectedResponseOperation.responses).join(', ');
|
|
66
|
+
// prettier-ignore
|
|
67
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy a '${status}' response defined for endpoint '${endpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} had status ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(status)}, but your API spec has no ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(status)} response defined for endpoint '${endpoint}'`, `Response statuses found for endpoint '${endpoint}' in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)(expectedResponseStatuses)}`);
|
|
68
|
+
}
|
|
69
|
+
// validationError.code === ErrorCode.InvalidBody
|
|
70
|
+
const responseDefinition = openApiSpec.findExpectedResponse(actualResponse);
|
|
71
|
+
// prettier-ignore
|
|
72
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy the '${status}' response defined for endpoint '${endpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} did not satisfy it because: ${validationError}`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} contained: ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(actualResponse.toString())}`, `The '${status}' response defined for endpoint '${endpoint}' in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)((0, utils_1.stringify)(responseDefinition))}`);
|
|
73
|
+
}
|
|
74
|
+
function getExpectReceivedNotToSatisfyApiSpecMsg(actualResponse, openApiSpec, hint) {
|
|
75
|
+
const { status, req } = actualResponse;
|
|
76
|
+
const responseDefinition = openApiSpec.findExpectedResponse(actualResponse);
|
|
77
|
+
const endpoint = `${req.method} ${openApiSpec.findOpenApiPathMatchingRequest(req)}`;
|
|
78
|
+
// prettier-ignore
|
|
79
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} not to satisfy the '${status}' response defined for endpoint '${endpoint}' in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} contained: ${(0, jest_matcher_utils_1.RECEIVED_COLOR)(actualResponse.toString())}`, `The '${status}' response defined for endpoint '${endpoint}' in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)((0, utils_1.stringify)(responseDefinition))}`);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=toSatisfyApiSpec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfyApiSpec.js","sourceRoot":"","sources":["../../src/matchers/toSatisfyApiSpec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfySchemaInApiSpec.d.ts","sourceRoot":"","sources":["../../src/matchers/toSatisfySchemaInApiSpec.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAA2B,MAAM,+BAA+B,CAAC;AAG1F,MAAM,CAAC,OAAO,WACZ,IAAI,EAAE,IAAI,CAAC,cAAc,EACzB,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,GACvB,IAAI,CAAC,mBAAmB,CAkD1B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const jest_matcher_utils_1 = require("jest-matcher-utils");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function default_1(received, schemaName, openApiSpec) {
|
|
7
|
+
const matcherHintOptions = {
|
|
8
|
+
comment: "Matches 'received' to a schema defined in your API spec, then validates 'received' against it",
|
|
9
|
+
...(this.isNot !== undefined && { isNot: this.isNot }),
|
|
10
|
+
...(this.promise !== undefined && { promise: this.promise }),
|
|
11
|
+
};
|
|
12
|
+
const hint = (0, jest_matcher_utils_1.matcherHint)('toSatisfySchemaInApiSpec', undefined, 'schemaName', matcherHintOptions);
|
|
13
|
+
const schema = openApiSpec.getSchemaObject(schemaName);
|
|
14
|
+
if (!schema) {
|
|
15
|
+
// alert users they are misusing this assertion
|
|
16
|
+
throw new Error((0, jest_matcher_utils_1.matcherErrorMessage)(hint, `${(0, jest_matcher_utils_1.EXPECTED_COLOR)('schemaName')} must match a schema in your API spec`, (0, jest_matcher_utils_1.printWithType)('schemaName', schemaName, jest_matcher_utils_1.printExpected)));
|
|
17
|
+
}
|
|
18
|
+
const validationError = openApiSpec.validateObject(received, schema);
|
|
19
|
+
const pass = !validationError;
|
|
20
|
+
const message = pass
|
|
21
|
+
? () => getExpectReceivedNotToSatisfySchemaInApiSpecMsg(received, schemaName, schema, hint)
|
|
22
|
+
: () => getExpectReceivedToSatisfySchemaInApiSpecMsg(received, schemaName, schema, validationError, hint);
|
|
23
|
+
return {
|
|
24
|
+
pass,
|
|
25
|
+
message,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function getExpectReceivedToSatisfySchemaInApiSpecMsg(received, schemaName, schema, validationError, hint) {
|
|
29
|
+
// prettier-ignore
|
|
30
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} to satisfy the '${schemaName}' schema defined in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} did not satisfy it because: ${validationError}`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} was: ${(0, jest_matcher_utils_1.RECEIVED_COLOR)((0, utils_1.stringify)(received))}`, `The '${schemaName}' schema in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)((0, utils_1.stringify)(schema))}`);
|
|
31
|
+
}
|
|
32
|
+
function getExpectReceivedNotToSatisfySchemaInApiSpecMsg(received, schemaName, schema, hint) {
|
|
33
|
+
// prettier-ignore
|
|
34
|
+
return (0, utils_1.joinWithNewLines)(hint, `expected ${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} not to satisfy the '${schemaName}' schema defined in your API spec`, `${(0, jest_matcher_utils_1.RECEIVED_COLOR)('received')} was: ${(0, jest_matcher_utils_1.RECEIVED_COLOR)((0, utils_1.stringify)(received))}`, `The '${schemaName}' schema in API spec: ${(0, jest_matcher_utils_1.EXPECTED_COLOR)((0, utils_1.stringify)(schema))}`);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=toSatisfySchemaInApiSpec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfySchemaInApiSpec.js","sourceRoot":"","sources":["../../src/matchers/toSatisfySchemaInApiSpec.ts"],"names":[],"mappings":";;AAYA,4BAuDC;AAnED,2DAQ4B;AAE5B,oCAAuD;AAEvD,mBAEE,QAAiB,EACjB,UAAkB,EAClB,WAAwB;IAExB,MAAM,kBAAkB,GAAuB;QAC7C,OAAO,EACL,+FAA+F;QACjG,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACtD,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;KAC7D,CAAC;IACF,MAAM,IAAI,GAAG,IAAA,gCAAW,EACtB,0BAA0B,EAC1B,SAAS,EACT,YAAY,EACZ,kBAAkB,CACnB,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,+CAA+C;QAC/C,MAAM,IAAI,KAAK,CACb,IAAA,wCAAmB,EACjB,IAAI,EACJ,GAAG,IAAA,mCAAc,EAAC,YAAY,CAAC,uCAAuC,EACtE,IAAA,kCAAa,EAAC,YAAY,EAAE,UAAU,EAAE,kCAAa,CAAC,CACvD,CACF,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,WAAW,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,CAAC,eAAe,CAAC;IAE9B,MAAM,OAAO,GAAG,IAAI;QAClB,CAAC,CAAC,GAAG,EAAE,CACH,+CAA+C,CAC7C,QAAQ,EACR,UAAU,EACV,MAAM,EACN,IAAI,CACL;QACL,CAAC,CAAC,GAAG,EAAE,CACH,4CAA4C,CAC1C,QAAQ,EACR,UAAU,EACV,MAAM,EACN,eAAe,EACf,IAAI,CACL,CAAC;IAER,OAAO;QACL,IAAI;QACJ,OAAO;KACR,CAAC;AACJ,CAAC;AAED,SAAS,4CAA4C,CACnD,QAAiB,EACjB,UAAkB,EAClB,MAAc,EACd,eAAgC,EAChC,IAAY;IAEZ,kBAAkB;IAClB,OAAO,IAAA,wBAAgB,EACrB,IAAI,EACJ,YAAY,IAAA,mCAAc,EAAC,UAAU,CAAC,oBAAoB,UAAU,mCAAmC,EACvG,GAAG,IAAA,mCAAc,EAAC,UAAU,CAAC,gCAAgC,eAAe,EAAE,EAC9E,GAAG,IAAA,mCAAc,EAAC,UAAU,CAAC,SAAS,IAAA,mCAAc,EAAC,IAAA,iBAAS,EAAC,QAAQ,CAAC,CAAC,EAAE,EAC3E,QAAQ,UAAU,yBAAyB,IAAA,mCAAc,EAAC,IAAA,iBAAS,EAAC,MAAM,CAAC,CAAC,EAAE,CAC/E,CAAC;AACJ,CAAC;AAED,SAAS,+CAA+C,CACtD,QAAiB,EACjB,UAAkB,EAClB,MAAc,EACd,IAAY;IAEZ,kBAAkB;IAClB,OAAO,IAAA,wBAAgB,EACrB,IAAI,EACJ,YAAY,IAAA,mCAAc,EAAC,UAAU,CAAC,wBAAwB,UAAU,mCAAmC,EAC3G,GAAG,IAAA,mCAAc,EAAC,UAAU,CAAC,SAAS,IAAA,mCAAc,EAAC,IAAA,iBAAS,EAAC,QAAQ,CAAC,CAAC,EAAE,EAC3E,QAAQ,UAAU,yBAAyB,IAAA,mCAAc,EAAC,IAAA,iBAAS,EAAC,MAAM,CAAC,CAAC,EAAE,CAC/E,CAAC;AACJ,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,KAAG,MACS,CAAC;AAEnD,eAAO,MAAM,gBAAgB,GAAI,GAAG,OAAO,MAAM,EAAE,KAAG,MAClC,CAAC"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.joinWithNewLines = exports.stringify = void 0;
|
|
4
|
+
const util_1 = require("util");
|
|
5
|
+
const stringify = (obj) => (0, util_1.inspect)(obj, { showHidden: false, depth: null });
|
|
6
|
+
exports.stringify = stringify;
|
|
7
|
+
const joinWithNewLines = (...lines) => lines.join('\n\n');
|
|
8
|
+
exports.joinWithNewLines = joinWithNewLines;
|
|
9
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAA,+BAA+B;AAExB,MAAM,SAAS,GAAG,CAAC,GAAY,EAAU,EAAE,CAChD,IAAA,cAAO,EAAC,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AADtC,QAAA,SAAS,aAC6B;AAE5C,MAAM,gBAAgB,GAAG,CAAC,GAAG,KAAe,EAAU,EAAE,CAC7D,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AADR,QAAA,gBAAgB,oBACR"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ehuelsmann/jest-openapi",
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"description": "Jest matchers for asserting that HTTP responses satisfy an OpenAPI spec",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"clean": "rimraf dist",
|
|
9
|
+
"clean:openapi-validator": "cd ../openapi-validator && yarn clean",
|
|
10
|
+
"format": "prettier --write ../../ --ignore-path ../../.prettierignore",
|
|
11
|
+
"lint": "tsc --noEmit --project tsconfig.eslint.json && eslint .",
|
|
12
|
+
"lint:fix": "yarn lint --fix",
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:watch": "jest --watch",
|
|
16
|
+
"test:coverage": "yarn clean && yarn clean:openapi-validator && jest --coverage",
|
|
17
|
+
"test:coverage:browse": "yarn test:coverage; open ../coverage/lcov-report/index.html",
|
|
18
|
+
"test:ci": "yarn format && yarn lint && yarn test:coverage",
|
|
19
|
+
"prepack": "yarn build"
|
|
20
|
+
},
|
|
21
|
+
"repository": "https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/jest-openapi",
|
|
22
|
+
"author": "rwalle61 <richard.lh.waller@gmail.com>",
|
|
23
|
+
"contributors": [
|
|
24
|
+
"Jonny Spruce <jspruce94@gmail.com>"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"jest",
|
|
29
|
+
"openapi",
|
|
30
|
+
"testing",
|
|
31
|
+
"response",
|
|
32
|
+
"validate",
|
|
33
|
+
"assertions"
|
|
34
|
+
],
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/openapi-library/OpenAPIValidators/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/openapi-library/OpenAPIValidators/tree/master/packages/jest-openapi#readme",
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist"
|
|
44
|
+
],
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/jest": "^30.0.0",
|
|
47
|
+
"@types/request-promise": "^4.1.48",
|
|
48
|
+
"@types/supertest": "^7.2.0",
|
|
49
|
+
"axios": "^1.15.0",
|
|
50
|
+
"eslint": "^7.11.0",
|
|
51
|
+
"eslint-plugin-jest": "^27.9.0",
|
|
52
|
+
"express": "^5.2.1",
|
|
53
|
+
"fs-extra": "^9.0.1",
|
|
54
|
+
"jest": "^30.3.0",
|
|
55
|
+
"request-promise": "^4.2.6",
|
|
56
|
+
"supertest": "^7.2.2",
|
|
57
|
+
"ts-jest": "^29.0.0",
|
|
58
|
+
"ts-node": "^9.1.1"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"jest-matcher-utils": "^29.0.0",
|
|
62
|
+
"@ehuelsmann/openapi-validator": "^0.15.0"
|
|
63
|
+
}
|
|
64
|
+
}
|