@flusys/nestjs-core 7.0.2 → 8.0.0-beta.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/README.md +2 -2
- package/config/index.d.ts +1 -1
- package/constants/index.d.ts +1 -1
- package/docs/docs.config.d.ts +1 -1
- package/docs/index.d.ts +1 -1
- package/fesm/229.js +729 -0
- package/fesm/config/index.js +126 -1
- package/fesm/constants/index.js +29 -1
- package/fesm/docs/index.js +288 -1
- package/fesm/index.js +124 -5
- package/fesm/interfaces/index.js +18 -4
- package/fesm/migration/cli.js +19 -2
- package/fesm/migration/index.js +45 -3
- package/fesm/runtime.js +85 -0
- package/fesm/utils/index.js +131 -1
- package/index.d.ts +5 -5
- package/interfaces/app-config.interfaces.d.ts +2 -1
- package/interfaces/database.interface.d.ts +1 -0
- package/interfaces/index.d.ts +4 -4
- package/interfaces/migration.interface.d.ts +2 -2
- package/migration/cli.d.ts +0 -1
- package/migration/datasource.factory.d.ts +1 -1
- package/migration/index.d.ts +3 -3
- package/migration/migration.cli.d.ts +1 -1
- package/migration/migration.runner.d.ts +1 -1
- package/package.json +25 -33
- package/utils/datasource-config.builder.d.ts +2 -2
- package/utils/index.d.ts +1 -1
- package/cjs/config/env-config.service.js +0 -162
- package/cjs/config/env-config.service.spec.js +0 -325
- package/cjs/config/index.js +0 -18
- package/cjs/constants/database.constants.js +0 -20
- package/cjs/constants/index.js +0 -18
- package/cjs/docs/docs.config.js +0 -276
- package/cjs/docs/docs.config.spec.js +0 -923
- package/cjs/docs/index.js +0 -18
- package/cjs/index.js +0 -23
- package/cjs/interfaces/app-config.interfaces.js +0 -4
- package/cjs/interfaces/base-entity.interface.js +0 -9
- package/cjs/interfaces/database.interface.js +0 -4
- package/cjs/interfaces/index.js +0 -21
- package/cjs/interfaces/migration.interface.js +0 -4
- package/cjs/migration/cli.js +0 -10
- package/cjs/migration/datasource.factory.js +0 -43
- package/cjs/migration/datasource.factory.spec.js +0 -113
- package/cjs/migration/index.js +0 -45
- package/cjs/migration/migration.cli.js +0 -231
- package/cjs/migration/migration.cli.spec.js +0 -293
- package/cjs/migration/migration.runner.js +0 -276
- package/cjs/migration/migration.runner.spec.js +0 -268
- package/cjs/utils/datasource-config.builder.js +0 -103
- package/cjs/utils/datasource-config.builder.spec.js +0 -232
- package/cjs/utils/index.js +0 -18
- package/fesm/config/env-config.service.js +0 -112
- package/fesm/config/env-config.service.spec.js +0 -321
- package/fesm/constants/database.constants.js +0 -2
- package/fesm/docs/docs.config.js +0 -258
- package/fesm/docs/docs.config.spec.js +0 -919
- package/fesm/interfaces/app-config.interfaces.js +0 -1
- package/fesm/interfaces/base-entity.interface.js +0 -6
- package/fesm/interfaces/database.interface.js +0 -1
- package/fesm/interfaces/migration.interface.js +0 -1
- package/fesm/migration/datasource.factory.js +0 -25
- package/fesm/migration/datasource.factory.spec.js +0 -109
- package/fesm/migration/migration.cli.js +0 -180
- package/fesm/migration/migration.cli.spec.js +0 -289
- package/fesm/migration/migration.runner.js +0 -202
- package/fesm/migration/migration.runner.spec.js +0 -264
- package/fesm/utils/datasource-config.builder.js +0 -84
- package/fesm/utils/datasource-config.builder.spec.js +0 -228
|
@@ -1,919 +0,0 @@
|
|
|
1
|
-
import { DocumentBuilder } from '@nestjs/swagger';
|
|
2
|
-
const mockCreateDocument = jest.fn();
|
|
3
|
-
const mockSetup = jest.fn();
|
|
4
|
-
jest.mock('@nestjs/swagger', ()=>{
|
|
5
|
-
const actual = jest.requireActual('@nestjs/swagger');
|
|
6
|
-
return {
|
|
7
|
-
...actual,
|
|
8
|
-
SwaggerModule: {
|
|
9
|
-
createDocument: (...args)=>mockCreateDocument(...args),
|
|
10
|
-
setup: (...args)=>mockSetup(...args)
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
});
|
|
14
|
-
import { setupModuleSwaggerDocs, setupSwaggerDocs } from './docs.config';
|
|
15
|
-
describe('docs.config', ()=>{
|
|
16
|
-
const mockApp = {};
|
|
17
|
-
function baseDocument(overrides = {}) {
|
|
18
|
-
return {
|
|
19
|
-
openapi: '3.0.0',
|
|
20
|
-
info: {
|
|
21
|
-
title: 't',
|
|
22
|
-
version: '1.0'
|
|
23
|
-
},
|
|
24
|
-
paths: {},
|
|
25
|
-
...overrides
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
beforeEach(()=>{
|
|
29
|
-
jest.clearAllMocks();
|
|
30
|
-
});
|
|
31
|
-
it('should build a document with the given title/description/version and register it', ()=>{
|
|
32
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
33
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
34
|
-
{
|
|
35
|
-
title: 'Auth API',
|
|
36
|
-
description: 'desc',
|
|
37
|
-
version: '2.0',
|
|
38
|
-
path: 'api/docs/auth'
|
|
39
|
-
}
|
|
40
|
-
]);
|
|
41
|
-
expect(mockCreateDocument).toHaveBeenCalledWith(mockApp, expect.any(Object), {});
|
|
42
|
-
expect(mockSetup).toHaveBeenCalledWith('api/docs/auth', mockApp, expect.any(Object));
|
|
43
|
-
});
|
|
44
|
-
it('should default the version to 1.0 when not provided', ()=>{
|
|
45
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
46
|
-
const buildSpy = jest.spyOn(DocumentBuilder.prototype, 'setVersion');
|
|
47
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
48
|
-
{
|
|
49
|
-
title: 't',
|
|
50
|
-
description: 'd',
|
|
51
|
-
path: 'p'
|
|
52
|
-
}
|
|
53
|
-
]);
|
|
54
|
-
expect(buildSpy).toHaveBeenCalledWith('1.0');
|
|
55
|
-
buildSpy.mockRestore();
|
|
56
|
-
});
|
|
57
|
-
it('should add bearer auth when bearerAuth is true', ()=>{
|
|
58
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
59
|
-
const bearerSpy = jest.spyOn(DocumentBuilder.prototype, 'addBearerAuth');
|
|
60
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
61
|
-
{
|
|
62
|
-
title: 't',
|
|
63
|
-
description: 'd',
|
|
64
|
-
path: 'p',
|
|
65
|
-
bearerAuth: true
|
|
66
|
-
}
|
|
67
|
-
]);
|
|
68
|
-
expect(bearerSpy).toHaveBeenCalled();
|
|
69
|
-
bearerSpy.mockRestore();
|
|
70
|
-
});
|
|
71
|
-
it('should not add bearer auth when bearerAuth is falsy', ()=>{
|
|
72
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
73
|
-
const bearerSpy = jest.spyOn(DocumentBuilder.prototype, 'addBearerAuth');
|
|
74
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
75
|
-
{
|
|
76
|
-
title: 't',
|
|
77
|
-
description: 'd',
|
|
78
|
-
path: 'p'
|
|
79
|
-
}
|
|
80
|
-
]);
|
|
81
|
-
expect(bearerSpy).not.toHaveBeenCalled();
|
|
82
|
-
bearerSpy.mockRestore();
|
|
83
|
-
});
|
|
84
|
-
it('should add global headers with defaults for optional fields', ()=>{
|
|
85
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
86
|
-
const headerSpy = jest.spyOn(DocumentBuilder.prototype, 'addGlobalParameters');
|
|
87
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
88
|
-
{
|
|
89
|
-
title: 't',
|
|
90
|
-
description: 'd',
|
|
91
|
-
path: 'p',
|
|
92
|
-
globalHeaders: [
|
|
93
|
-
{
|
|
94
|
-
name: 'X-Tenant-Id',
|
|
95
|
-
description: 'tenant'
|
|
96
|
-
}
|
|
97
|
-
]
|
|
98
|
-
}
|
|
99
|
-
]);
|
|
100
|
-
expect(headerSpy).toHaveBeenCalledWith({
|
|
101
|
-
name: 'X-Tenant-Id',
|
|
102
|
-
in: 'header',
|
|
103
|
-
description: 'tenant',
|
|
104
|
-
required: false,
|
|
105
|
-
schema: {
|
|
106
|
-
type: 'string',
|
|
107
|
-
example: ''
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
headerSpy.mockRestore();
|
|
111
|
-
});
|
|
112
|
-
it('should pass required/example through for global headers when provided', ()=>{
|
|
113
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
114
|
-
const headerSpy = jest.spyOn(DocumentBuilder.prototype, 'addGlobalParameters');
|
|
115
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
116
|
-
{
|
|
117
|
-
title: 't',
|
|
118
|
-
description: 'd',
|
|
119
|
-
path: 'p',
|
|
120
|
-
globalHeaders: [
|
|
121
|
-
{
|
|
122
|
-
name: 'X-Tenant-Id',
|
|
123
|
-
description: 'tenant',
|
|
124
|
-
required: true,
|
|
125
|
-
example: 'tenant-1'
|
|
126
|
-
}
|
|
127
|
-
]
|
|
128
|
-
}
|
|
129
|
-
]);
|
|
130
|
-
expect(headerSpy).toHaveBeenCalledWith(expect.objectContaining({
|
|
131
|
-
required: true,
|
|
132
|
-
schema: {
|
|
133
|
-
type: 'string',
|
|
134
|
-
example: 'tenant-1'
|
|
135
|
-
}
|
|
136
|
-
}));
|
|
137
|
-
headerSpy.mockRestore();
|
|
138
|
-
});
|
|
139
|
-
it('should scope the document to specific modules when provided', ()=>{
|
|
140
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
141
|
-
let FakeModule = class FakeModule {
|
|
142
|
-
};
|
|
143
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
144
|
-
{
|
|
145
|
-
title: 't',
|
|
146
|
-
description: 'd',
|
|
147
|
-
path: 'p',
|
|
148
|
-
modules: [
|
|
149
|
-
FakeModule
|
|
150
|
-
]
|
|
151
|
-
}
|
|
152
|
-
]);
|
|
153
|
-
expect(mockCreateDocument).toHaveBeenCalledWith(mockApp, expect.any(Object), {
|
|
154
|
-
include: [
|
|
155
|
-
FakeModule
|
|
156
|
-
]
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
it('should set up multiple module configs independently', ()=>{
|
|
160
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
161
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
162
|
-
{
|
|
163
|
-
title: 'A',
|
|
164
|
-
description: 'a',
|
|
165
|
-
path: 'a'
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
title: 'B',
|
|
169
|
-
description: 'b',
|
|
170
|
-
path: 'b'
|
|
171
|
-
}
|
|
172
|
-
]);
|
|
173
|
-
expect(mockCreateDocument).toHaveBeenCalledTimes(2);
|
|
174
|
-
expect(mockSetup).toHaveBeenCalledTimes(2);
|
|
175
|
-
expect(mockSetup).toHaveBeenNthCalledWith(1, 'a', mockApp, expect.any(Object));
|
|
176
|
-
expect(mockSetup).toHaveBeenNthCalledWith(2, 'b', mockApp, expect.any(Object));
|
|
177
|
-
});
|
|
178
|
-
it('setupSwaggerDocs should forward all configs as varargs to setupModuleSwaggerDocs', ()=>{
|
|
179
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
180
|
-
setupSwaggerDocs(mockApp, {
|
|
181
|
-
title: 'A',
|
|
182
|
-
description: 'a',
|
|
183
|
-
path: 'a'
|
|
184
|
-
}, {
|
|
185
|
-
title: 'B',
|
|
186
|
-
description: 'b',
|
|
187
|
-
path: 'b'
|
|
188
|
-
});
|
|
189
|
-
expect(mockSetup).toHaveBeenCalledTimes(2);
|
|
190
|
-
});
|
|
191
|
-
describe('excludeSchemaProperties', ()=>{
|
|
192
|
-
it('should remove excluded properties and drop them from the required array', ()=>{
|
|
193
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
194
|
-
components: {
|
|
195
|
-
schemas: {
|
|
196
|
-
User: {
|
|
197
|
-
properties: {
|
|
198
|
-
id: {
|
|
199
|
-
type: 'string'
|
|
200
|
-
},
|
|
201
|
-
password: {
|
|
202
|
-
type: 'string'
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
required: [
|
|
206
|
-
'id',
|
|
207
|
-
'password'
|
|
208
|
-
]
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}));
|
|
213
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
214
|
-
{
|
|
215
|
-
title: 't',
|
|
216
|
-
description: 'd',
|
|
217
|
-
path: 'p',
|
|
218
|
-
excludeSchemaProperties: [
|
|
219
|
-
{
|
|
220
|
-
schemaName: 'User',
|
|
221
|
-
properties: [
|
|
222
|
-
'password'
|
|
223
|
-
]
|
|
224
|
-
}
|
|
225
|
-
]
|
|
226
|
-
}
|
|
227
|
-
]);
|
|
228
|
-
const document = mockSetup.mock.calls[0][2];
|
|
229
|
-
const userSchema = document.components.schemas.User;
|
|
230
|
-
expect(userSchema.properties).toEqual({
|
|
231
|
-
id: {
|
|
232
|
-
type: 'string'
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
expect(userSchema.required).toEqual([
|
|
236
|
-
'id'
|
|
237
|
-
]);
|
|
238
|
-
});
|
|
239
|
-
// BUG: when filteredRequired becomes empty, the code spreads `{}` (falsy branch) instead of
|
|
240
|
-
// `{ required: undefined }`, so the stale `required` array from `...schema` survives untouched —
|
|
241
|
-
// the excluded property stays listed as required even though it was removed from `properties`.
|
|
242
|
-
it('should currently leave a stale required array when every required prop is excluded (known bug)', ()=>{
|
|
243
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
244
|
-
components: {
|
|
245
|
-
schemas: {
|
|
246
|
-
User: {
|
|
247
|
-
properties: {
|
|
248
|
-
password: {
|
|
249
|
-
type: 'string'
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
required: [
|
|
253
|
-
'password'
|
|
254
|
-
]
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}));
|
|
259
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
260
|
-
{
|
|
261
|
-
title: 't',
|
|
262
|
-
description: 'd',
|
|
263
|
-
path: 'p',
|
|
264
|
-
excludeSchemaProperties: [
|
|
265
|
-
{
|
|
266
|
-
schemaName: 'User',
|
|
267
|
-
properties: [
|
|
268
|
-
'password'
|
|
269
|
-
]
|
|
270
|
-
}
|
|
271
|
-
]
|
|
272
|
-
}
|
|
273
|
-
]);
|
|
274
|
-
const document = mockSetup.mock.calls[0][2];
|
|
275
|
-
const userSchema = document.components.schemas.User;
|
|
276
|
-
expect(userSchema.properties).toEqual({});
|
|
277
|
-
expect(userSchema.required).toEqual([
|
|
278
|
-
'password'
|
|
279
|
-
]);
|
|
280
|
-
});
|
|
281
|
-
it('should be a no-op when the schema does not exist', ()=>{
|
|
282
|
-
const doc = baseDocument({
|
|
283
|
-
components: {
|
|
284
|
-
schemas: {}
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
mockCreateDocument.mockReturnValue(doc);
|
|
288
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
289
|
-
{
|
|
290
|
-
title: 't',
|
|
291
|
-
description: 'd',
|
|
292
|
-
path: 'p',
|
|
293
|
-
excludeSchemaProperties: [
|
|
294
|
-
{
|
|
295
|
-
schemaName: 'Missing',
|
|
296
|
-
properties: [
|
|
297
|
-
'x'
|
|
298
|
-
]
|
|
299
|
-
}
|
|
300
|
-
]
|
|
301
|
-
}
|
|
302
|
-
]);
|
|
303
|
-
const document = mockSetup.mock.calls[0][2];
|
|
304
|
-
expect(document.components.schemas).toEqual({});
|
|
305
|
-
});
|
|
306
|
-
it('should be a no-op when there are no components/schemas on the document', ()=>{
|
|
307
|
-
mockCreateDocument.mockReturnValue(baseDocument());
|
|
308
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
309
|
-
{
|
|
310
|
-
title: 't',
|
|
311
|
-
description: 'd',
|
|
312
|
-
path: 'p',
|
|
313
|
-
excludeSchemaProperties: [
|
|
314
|
-
{
|
|
315
|
-
schemaName: 'User',
|
|
316
|
-
properties: [
|
|
317
|
-
'x'
|
|
318
|
-
]
|
|
319
|
-
}
|
|
320
|
-
]
|
|
321
|
-
}
|
|
322
|
-
]);
|
|
323
|
-
const document = mockSetup.mock.calls[0][2];
|
|
324
|
-
expect(document.components).toBeUndefined();
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
describe('excludeQueryParameters', ()=>{
|
|
328
|
-
it('should strip matching query parameters from operations matching the path pattern', ()=>{
|
|
329
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
330
|
-
paths: {
|
|
331
|
-
'/users': {
|
|
332
|
-
get: {
|
|
333
|
-
parameters: [
|
|
334
|
-
{
|
|
335
|
-
name: 'internalDebug',
|
|
336
|
-
in: 'query'
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
name: 'page',
|
|
340
|
-
in: 'query'
|
|
341
|
-
}
|
|
342
|
-
]
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}));
|
|
347
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
348
|
-
{
|
|
349
|
-
title: 't',
|
|
350
|
-
description: 'd',
|
|
351
|
-
path: 'p',
|
|
352
|
-
excludeQueryParameters: [
|
|
353
|
-
{
|
|
354
|
-
pathPattern: '/users',
|
|
355
|
-
parameters: [
|
|
356
|
-
'internalDebug'
|
|
357
|
-
]
|
|
358
|
-
}
|
|
359
|
-
]
|
|
360
|
-
}
|
|
361
|
-
]);
|
|
362
|
-
const document = mockSetup.mock.calls[0][2];
|
|
363
|
-
const params = document.paths['/users'].get.parameters;
|
|
364
|
-
expect(params).toEqual([
|
|
365
|
-
{
|
|
366
|
-
name: 'page',
|
|
367
|
-
in: 'query'
|
|
368
|
-
}
|
|
369
|
-
]);
|
|
370
|
-
});
|
|
371
|
-
it('should only strip parameters for the specified method when method is set', ()=>{
|
|
372
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
373
|
-
paths: {
|
|
374
|
-
'/users': {
|
|
375
|
-
get: {
|
|
376
|
-
parameters: [
|
|
377
|
-
{
|
|
378
|
-
name: 'debug',
|
|
379
|
-
in: 'query'
|
|
380
|
-
}
|
|
381
|
-
]
|
|
382
|
-
},
|
|
383
|
-
post: {
|
|
384
|
-
parameters: [
|
|
385
|
-
{
|
|
386
|
-
name: 'debug',
|
|
387
|
-
in: 'query'
|
|
388
|
-
}
|
|
389
|
-
]
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}));
|
|
394
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
395
|
-
{
|
|
396
|
-
title: 't',
|
|
397
|
-
description: 'd',
|
|
398
|
-
path: 'p',
|
|
399
|
-
excludeQueryParameters: [
|
|
400
|
-
{
|
|
401
|
-
pathPattern: '/users',
|
|
402
|
-
method: 'get',
|
|
403
|
-
parameters: [
|
|
404
|
-
'debug'
|
|
405
|
-
]
|
|
406
|
-
}
|
|
407
|
-
]
|
|
408
|
-
}
|
|
409
|
-
]);
|
|
410
|
-
const document = mockSetup.mock.calls[0][2];
|
|
411
|
-
expect(document.paths['/users'].get.parameters).toEqual([]);
|
|
412
|
-
expect(document.paths['/users'].post.parameters).toEqual([
|
|
413
|
-
{
|
|
414
|
-
name: 'debug',
|
|
415
|
-
in: 'query'
|
|
416
|
-
}
|
|
417
|
-
]);
|
|
418
|
-
});
|
|
419
|
-
it('should not touch parameters that are not in-query', ()=>{
|
|
420
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
421
|
-
paths: {
|
|
422
|
-
'/users/{id}': {
|
|
423
|
-
get: {
|
|
424
|
-
parameters: [
|
|
425
|
-
{
|
|
426
|
-
name: 'id',
|
|
427
|
-
in: 'path'
|
|
428
|
-
}
|
|
429
|
-
]
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}));
|
|
434
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
435
|
-
{
|
|
436
|
-
title: 't',
|
|
437
|
-
description: 'd',
|
|
438
|
-
path: 'p',
|
|
439
|
-
excludeQueryParameters: [
|
|
440
|
-
{
|
|
441
|
-
pathPattern: '/users/{id}',
|
|
442
|
-
parameters: [
|
|
443
|
-
'id'
|
|
444
|
-
]
|
|
445
|
-
}
|
|
446
|
-
]
|
|
447
|
-
}
|
|
448
|
-
]);
|
|
449
|
-
const document = mockSetup.mock.calls[0][2];
|
|
450
|
-
expect(document.paths['/users/{id}'].get.parameters).toEqual([
|
|
451
|
-
{
|
|
452
|
-
name: 'id',
|
|
453
|
-
in: 'path'
|
|
454
|
-
}
|
|
455
|
-
]);
|
|
456
|
-
});
|
|
457
|
-
it('should leave non-matching paths untouched', ()=>{
|
|
458
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
459
|
-
paths: {
|
|
460
|
-
'/orders': {
|
|
461
|
-
get: {
|
|
462
|
-
parameters: [
|
|
463
|
-
{
|
|
464
|
-
name: 'debug',
|
|
465
|
-
in: 'query'
|
|
466
|
-
}
|
|
467
|
-
]
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}));
|
|
472
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
473
|
-
{
|
|
474
|
-
title: 't',
|
|
475
|
-
description: 'd',
|
|
476
|
-
path: 'p',
|
|
477
|
-
excludeQueryParameters: [
|
|
478
|
-
{
|
|
479
|
-
pathPattern: '/users',
|
|
480
|
-
parameters: [
|
|
481
|
-
'debug'
|
|
482
|
-
]
|
|
483
|
-
}
|
|
484
|
-
]
|
|
485
|
-
}
|
|
486
|
-
]);
|
|
487
|
-
const document = mockSetup.mock.calls[0][2];
|
|
488
|
-
expect(document.paths['/orders'].get.parameters).toEqual([
|
|
489
|
-
{
|
|
490
|
-
name: 'debug',
|
|
491
|
-
in: 'query'
|
|
492
|
-
}
|
|
493
|
-
]);
|
|
494
|
-
});
|
|
495
|
-
});
|
|
496
|
-
describe('excludeExamples', ()=>{
|
|
497
|
-
it('should remove named examples from response media types without mutating the source document', ()=>{
|
|
498
|
-
const originalDoc = baseDocument({
|
|
499
|
-
paths: {
|
|
500
|
-
'/users': {
|
|
501
|
-
get: {
|
|
502
|
-
responses: {
|
|
503
|
-
'200': {
|
|
504
|
-
content: {
|
|
505
|
-
'application/json': {
|
|
506
|
-
examples: {
|
|
507
|
-
admin: {
|
|
508
|
-
value: {}
|
|
509
|
-
},
|
|
510
|
-
guest: {
|
|
511
|
-
value: {}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
mockCreateDocument.mockReturnValue(originalDoc);
|
|
523
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
524
|
-
{
|
|
525
|
-
title: 't',
|
|
526
|
-
description: 'd',
|
|
527
|
-
path: 'p',
|
|
528
|
-
excludeExamples: [
|
|
529
|
-
{
|
|
530
|
-
pathPattern: '/users',
|
|
531
|
-
examples: [
|
|
532
|
-
'admin'
|
|
533
|
-
]
|
|
534
|
-
}
|
|
535
|
-
]
|
|
536
|
-
}
|
|
537
|
-
]);
|
|
538
|
-
const document = mockSetup.mock.calls[0][2];
|
|
539
|
-
const examples = document.paths['/users'].get.responses['200'].content['application/json'].examples;
|
|
540
|
-
expect(examples).toEqual({
|
|
541
|
-
guest: {
|
|
542
|
-
value: {}
|
|
543
|
-
}
|
|
544
|
-
});
|
|
545
|
-
// original untouched
|
|
546
|
-
const originalExamples = originalDoc.paths['/users'].get.responses['200'].content['application/json'].examples;
|
|
547
|
-
expect(originalExamples).toEqual({
|
|
548
|
-
admin: {
|
|
549
|
-
value: {}
|
|
550
|
-
},
|
|
551
|
-
guest: {
|
|
552
|
-
value: {}
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
});
|
|
556
|
-
it('should be a no-op when responses have no examples', ()=>{
|
|
557
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
558
|
-
paths: {
|
|
559
|
-
'/users': {
|
|
560
|
-
get: {
|
|
561
|
-
responses: {
|
|
562
|
-
'200': {
|
|
563
|
-
content: {}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}));
|
|
570
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
571
|
-
{
|
|
572
|
-
title: 't',
|
|
573
|
-
description: 'd',
|
|
574
|
-
path: 'p',
|
|
575
|
-
excludeExamples: [
|
|
576
|
-
{
|
|
577
|
-
pathPattern: '/users',
|
|
578
|
-
examples: [
|
|
579
|
-
'admin'
|
|
580
|
-
]
|
|
581
|
-
}
|
|
582
|
-
]
|
|
583
|
-
}
|
|
584
|
-
]);
|
|
585
|
-
const document = mockSetup.mock.calls[0][2];
|
|
586
|
-
expect(document.paths['/users'].get.responses['200'].content).toEqual({});
|
|
587
|
-
});
|
|
588
|
-
});
|
|
589
|
-
describe('excludePaths', ()=>{
|
|
590
|
-
it('should remove paths matching a wildcard pattern', ()=>{
|
|
591
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
592
|
-
paths: {
|
|
593
|
-
'/internal/health': {
|
|
594
|
-
get: {}
|
|
595
|
-
},
|
|
596
|
-
'/users': {
|
|
597
|
-
get: {}
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
}));
|
|
601
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
602
|
-
{
|
|
603
|
-
title: 't',
|
|
604
|
-
description: 'd',
|
|
605
|
-
path: 'p',
|
|
606
|
-
excludePaths: [
|
|
607
|
-
'/internal/*'
|
|
608
|
-
]
|
|
609
|
-
}
|
|
610
|
-
]);
|
|
611
|
-
const document = mockSetup.mock.calls[0][2];
|
|
612
|
-
expect(Object.keys(document.paths)).toEqual([
|
|
613
|
-
'/users'
|
|
614
|
-
]);
|
|
615
|
-
});
|
|
616
|
-
// BUG: pathMatchesPattern replaces single `*` before `**`, so by the time the `**` replace
|
|
617
|
-
// runs there are no literal `**` left to match (they've already become `[^/]+[^/]+`) — the
|
|
618
|
-
// "match across slashes" wildcard is effectively dead code and behaves like two single-segment
|
|
619
|
-
// wildcards instead, so a pattern like '/internal/**' will NOT exclude multi-segment paths.
|
|
620
|
-
it('should currently fail to match multi-segment paths with ** (known bug)', ()=>{
|
|
621
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
622
|
-
paths: {
|
|
623
|
-
'/internal/a/b/c': {
|
|
624
|
-
get: {}
|
|
625
|
-
},
|
|
626
|
-
'/internal/ab': {
|
|
627
|
-
get: {}
|
|
628
|
-
},
|
|
629
|
-
'/users': {
|
|
630
|
-
get: {}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}));
|
|
634
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
635
|
-
{
|
|
636
|
-
title: 't',
|
|
637
|
-
description: 'd',
|
|
638
|
-
path: 'p',
|
|
639
|
-
excludePaths: [
|
|
640
|
-
'/internal/**'
|
|
641
|
-
]
|
|
642
|
-
}
|
|
643
|
-
]);
|
|
644
|
-
const document = mockSetup.mock.calls[0][2];
|
|
645
|
-
// '**' can't cross the extra path segment boundaries, so the nested path survives.
|
|
646
|
-
expect(Object.keys(document.paths).sort()).toEqual([
|
|
647
|
-
'/internal/a/b/c',
|
|
648
|
-
'/users'
|
|
649
|
-
].sort());
|
|
650
|
-
});
|
|
651
|
-
it('should leave paths untouched when excludePaths is empty', ()=>{
|
|
652
|
-
const doc = baseDocument({
|
|
653
|
-
paths: {
|
|
654
|
-
'/users': {
|
|
655
|
-
get: {}
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
});
|
|
659
|
-
mockCreateDocument.mockReturnValue(doc);
|
|
660
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
661
|
-
{
|
|
662
|
-
title: 't',
|
|
663
|
-
description: 'd',
|
|
664
|
-
path: 'p',
|
|
665
|
-
excludePaths: []
|
|
666
|
-
}
|
|
667
|
-
]);
|
|
668
|
-
const document = mockSetup.mock.calls[0][2];
|
|
669
|
-
expect(document.paths).toEqual(doc.paths);
|
|
670
|
-
});
|
|
671
|
-
});
|
|
672
|
-
describe('excludeTags', ()=>{
|
|
673
|
-
it('should drop operations that carry an excluded tag, case-insensitively', ()=>{
|
|
674
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
675
|
-
paths: {
|
|
676
|
-
'/internal': {
|
|
677
|
-
get: {
|
|
678
|
-
tags: [
|
|
679
|
-
'Internal'
|
|
680
|
-
]
|
|
681
|
-
}
|
|
682
|
-
},
|
|
683
|
-
'/users': {
|
|
684
|
-
get: {
|
|
685
|
-
tags: [
|
|
686
|
-
'Users'
|
|
687
|
-
]
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
},
|
|
691
|
-
tags: [
|
|
692
|
-
{
|
|
693
|
-
name: 'Internal'
|
|
694
|
-
},
|
|
695
|
-
{
|
|
696
|
-
name: 'Users'
|
|
697
|
-
}
|
|
698
|
-
]
|
|
699
|
-
}));
|
|
700
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
701
|
-
{
|
|
702
|
-
title: 't',
|
|
703
|
-
description: 'd',
|
|
704
|
-
path: 'p',
|
|
705
|
-
excludeTags: [
|
|
706
|
-
'internal'
|
|
707
|
-
]
|
|
708
|
-
}
|
|
709
|
-
]);
|
|
710
|
-
const document = mockSetup.mock.calls[0][2];
|
|
711
|
-
expect(Object.keys(document.paths)).toEqual([
|
|
712
|
-
'/users'
|
|
713
|
-
]);
|
|
714
|
-
expect(document.tags).toEqual([
|
|
715
|
-
{
|
|
716
|
-
name: 'Users'
|
|
717
|
-
}
|
|
718
|
-
]);
|
|
719
|
-
});
|
|
720
|
-
it('should drop the whole path entry when every operation is excluded', ()=>{
|
|
721
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
722
|
-
paths: {
|
|
723
|
-
'/internal': {
|
|
724
|
-
get: {
|
|
725
|
-
tags: [
|
|
726
|
-
'Internal'
|
|
727
|
-
]
|
|
728
|
-
},
|
|
729
|
-
post: {
|
|
730
|
-
tags: [
|
|
731
|
-
'Internal'
|
|
732
|
-
]
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
}));
|
|
737
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
738
|
-
{
|
|
739
|
-
title: 't',
|
|
740
|
-
description: 'd',
|
|
741
|
-
path: 'p',
|
|
742
|
-
excludeTags: [
|
|
743
|
-
'Internal'
|
|
744
|
-
]
|
|
745
|
-
}
|
|
746
|
-
]);
|
|
747
|
-
const document = mockSetup.mock.calls[0][2];
|
|
748
|
-
expect(document.paths).toEqual({});
|
|
749
|
-
});
|
|
750
|
-
it('should keep a path when only some of its operations are excluded', ()=>{
|
|
751
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
752
|
-
paths: {
|
|
753
|
-
'/mixed': {
|
|
754
|
-
get: {
|
|
755
|
-
tags: [
|
|
756
|
-
'Public'
|
|
757
|
-
]
|
|
758
|
-
},
|
|
759
|
-
post: {
|
|
760
|
-
tags: [
|
|
761
|
-
'Internal'
|
|
762
|
-
]
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}));
|
|
767
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
768
|
-
{
|
|
769
|
-
title: 't',
|
|
770
|
-
description: 'd',
|
|
771
|
-
path: 'p',
|
|
772
|
-
excludeTags: [
|
|
773
|
-
'Internal'
|
|
774
|
-
]
|
|
775
|
-
}
|
|
776
|
-
]);
|
|
777
|
-
const document = mockSetup.mock.calls[0][2];
|
|
778
|
-
expect(Object.keys(document.paths['/mixed'])).toEqual([
|
|
779
|
-
'get'
|
|
780
|
-
]);
|
|
781
|
-
});
|
|
782
|
-
it('should preserve non-operation keys like shared parameters on the path item', ()=>{
|
|
783
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
784
|
-
paths: {
|
|
785
|
-
'/mixed': {
|
|
786
|
-
parameters: [
|
|
787
|
-
{
|
|
788
|
-
name: 'shared',
|
|
789
|
-
in: 'query'
|
|
790
|
-
}
|
|
791
|
-
],
|
|
792
|
-
get: {
|
|
793
|
-
tags: [
|
|
794
|
-
'Public'
|
|
795
|
-
]
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
}));
|
|
800
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
801
|
-
{
|
|
802
|
-
title: 't',
|
|
803
|
-
description: 'd',
|
|
804
|
-
path: 'p',
|
|
805
|
-
excludeTags: [
|
|
806
|
-
'Nonexistent'
|
|
807
|
-
]
|
|
808
|
-
}
|
|
809
|
-
]);
|
|
810
|
-
const document = mockSetup.mock.calls[0][2];
|
|
811
|
-
expect(document.paths['/mixed'].parameters).toEqual([
|
|
812
|
-
{
|
|
813
|
-
name: 'shared',
|
|
814
|
-
in: 'query'
|
|
815
|
-
}
|
|
816
|
-
]);
|
|
817
|
-
});
|
|
818
|
-
it('should be a no-op when excludeTags is empty', ()=>{
|
|
819
|
-
const doc = baseDocument({
|
|
820
|
-
paths: {
|
|
821
|
-
'/users': {
|
|
822
|
-
get: {
|
|
823
|
-
tags: [
|
|
824
|
-
'Users'
|
|
825
|
-
]
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
},
|
|
829
|
-
tags: [
|
|
830
|
-
{
|
|
831
|
-
name: 'Users'
|
|
832
|
-
}
|
|
833
|
-
]
|
|
834
|
-
});
|
|
835
|
-
mockCreateDocument.mockReturnValue(doc);
|
|
836
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
837
|
-
{
|
|
838
|
-
title: 't',
|
|
839
|
-
description: 'd',
|
|
840
|
-
path: 'p',
|
|
841
|
-
excludeTags: []
|
|
842
|
-
}
|
|
843
|
-
]);
|
|
844
|
-
const document = mockSetup.mock.calls[0][2];
|
|
845
|
-
expect(document).toBe(doc);
|
|
846
|
-
});
|
|
847
|
-
});
|
|
848
|
-
it('should apply exclusion filters in combination', ()=>{
|
|
849
|
-
mockCreateDocument.mockReturnValue(baseDocument({
|
|
850
|
-
paths: {
|
|
851
|
-
'/internal/debug': {
|
|
852
|
-
get: {
|
|
853
|
-
tags: [
|
|
854
|
-
'Internal'
|
|
855
|
-
]
|
|
856
|
-
}
|
|
857
|
-
},
|
|
858
|
-
'/users': {
|
|
859
|
-
get: {
|
|
860
|
-
tags: [
|
|
861
|
-
'Users'
|
|
862
|
-
],
|
|
863
|
-
parameters: [
|
|
864
|
-
{
|
|
865
|
-
name: 'debug',
|
|
866
|
-
in: 'query'
|
|
867
|
-
}
|
|
868
|
-
]
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
},
|
|
872
|
-
components: {
|
|
873
|
-
schemas: {
|
|
874
|
-
User: {
|
|
875
|
-
properties: {
|
|
876
|
-
password: {}
|
|
877
|
-
},
|
|
878
|
-
required: [
|
|
879
|
-
'password'
|
|
880
|
-
]
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
}));
|
|
885
|
-
const config = {
|
|
886
|
-
title: 't',
|
|
887
|
-
description: 'd',
|
|
888
|
-
path: 'p',
|
|
889
|
-
excludePaths: [
|
|
890
|
-
'/internal/**'
|
|
891
|
-
],
|
|
892
|
-
excludeSchemaProperties: [
|
|
893
|
-
{
|
|
894
|
-
schemaName: 'User',
|
|
895
|
-
properties: [
|
|
896
|
-
'password'
|
|
897
|
-
]
|
|
898
|
-
}
|
|
899
|
-
],
|
|
900
|
-
excludeQueryParameters: [
|
|
901
|
-
{
|
|
902
|
-
pathPattern: '/users',
|
|
903
|
-
parameters: [
|
|
904
|
-
'debug'
|
|
905
|
-
]
|
|
906
|
-
}
|
|
907
|
-
]
|
|
908
|
-
};
|
|
909
|
-
setupModuleSwaggerDocs(mockApp, [
|
|
910
|
-
config
|
|
911
|
-
]);
|
|
912
|
-
const document = mockSetup.mock.calls[0][2];
|
|
913
|
-
expect(Object.keys(document.paths)).toEqual([
|
|
914
|
-
'/users'
|
|
915
|
-
]);
|
|
916
|
-
expect(document.paths['/users'].get.parameters).toEqual([]);
|
|
917
|
-
expect(document.components.schemas.User.properties).toEqual({});
|
|
918
|
-
});
|
|
919
|
-
});
|