@e22m4u/js-openapi 0.0.5 → 0.0.7

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.
Files changed (70) hide show
  1. package/README.md +226 -146
  2. package/dist/cjs/index.cjs +2025 -2092
  3. package/package.json +10 -8
  4. package/schema/openapi-3-1/dialect/base.js +21 -0
  5. package/schema/openapi-3-1/meta/base.js +76 -0
  6. package/schema/openapi-3-1/schema-base.js +32 -0
  7. package/schema/openapi-3-1/schema.js +1403 -0
  8. package/src/ajv.js +32 -0
  9. package/src/errors/index.d.ts +1 -1
  10. package/src/errors/index.js +1 -1
  11. package/src/errors/oa-document-object-validation-error.d.ts +6 -0
  12. package/src/errors/oa-document-object-validation-error.js +6 -0
  13. package/src/errors/oa-document-object-validation-error.spec.js +10 -0
  14. package/src/index.d.ts +1 -3
  15. package/src/index.js +1 -3
  16. package/src/json-pointer/resolve-json-pointer.js +1 -1
  17. package/src/json-pointer/unescape-json-pointer.d.ts +1 -2
  18. package/src/oa-document-builder.d.ts +302 -111
  19. package/src/oa-document-builder.js +208 -142
  20. package/src/oa-document-builder.spec.js +1411 -0
  21. package/src/oa-document-object/index.d.ts +1 -1
  22. package/src/oa-document-object/index.js +1 -1
  23. package/src/oa-document-object/validate-oa-document-object.d.ts +18 -0
  24. package/src/oa-document-object/validate-oa-document-object.js +53 -0
  25. package/src/oa-document-object/validate-oa-document-object.spec.js +122 -0
  26. package/src/{oa-document-scope.d.ts → oa-operation-group.d.ts} +7 -7
  27. package/src/{oa-document-scope.js → oa-operation-group.js} +101 -46
  28. package/src/oa-operation-group.spec.js +544 -0
  29. package/src/oa-reference-object/is-oa-reference-object.js +1 -1
  30. package/src/oa-reference-object/is-oa-reference-object.spec.js +1 -1
  31. package/src/oa-reference-object/oa-ref.js +7 -0
  32. package/src/oa-reference-object/resolve-oa-reference-object.js +1 -11
  33. package/src/oa-reference-object/resolve-oa-reference-object.spec.js +0 -10
  34. package/src/oa-specification.d.ts +55 -66
  35. package/src/oa-specification.js +11 -22
  36. package/src/data-type/index.d.ts +0 -1
  37. package/src/data-type/index.js +0 -1
  38. package/src/data-type/infer-openapi-data-type.d.ts +0 -30
  39. package/src/data-type/infer-openapi-data-type.js +0 -38
  40. package/src/data-validation/data-format-validator-map.d.ts +0 -13
  41. package/src/data-validation/data-format-validator-map.js +0 -36
  42. package/src/data-validation/data-format-validator-map.spec.js +0 -39
  43. package/src/data-validation/data-format-validators.d.ts +0 -84
  44. package/src/data-validation/data-format-validators.js +0 -217
  45. package/src/data-validation/index.d.ts +0 -3
  46. package/src/data-validation/index.js +0 -3
  47. package/src/data-validation/validate-data-with-openapi-schema.d.ts +0 -46
  48. package/src/data-validation/validate-data-with-openapi-schema.js +0 -1913
  49. package/src/data-validation/validate-data-with-openapi-schema.spec.js +0 -6953
  50. package/src/errors/oa-data-validation-error.d.ts +0 -6
  51. package/src/errors/oa-data-validation-error.js +0 -6
  52. package/src/errors/oa-data-validation-error.spec.js +0 -17
  53. package/src/oa-document-object/validate-shallow-oa-document.d.ts +0 -10
  54. package/src/oa-document-object/validate-shallow-oa-document.js +0 -209
  55. package/src/oa-document-object/validate-shallow-oa-document.spec.js +0 -362
  56. package/src/utils/count-unicode.d.ts +0 -11
  57. package/src/utils/count-unicode.js +0 -15
  58. package/src/utils/index.d.ts +0 -5
  59. package/src/utils/index.js +0 -5
  60. package/src/utils/join-path.d.ts +0 -6
  61. package/src/utils/join-path.js +0 -36
  62. package/src/utils/join-path.spec.js +0 -104
  63. package/src/utils/normalize-path.d.ts +0 -12
  64. package/src/utils/normalize-path.js +0 -22
  65. package/src/utils/normalize-path.spec.js +0 -56
  66. package/src/utils/to-pascal-case.d.ts +0 -6
  67. package/src/utils/to-pascal-case.js +0 -26
  68. package/src/utils/to-pascal-case.spec.js +0 -15
  69. package/src/utils/to-spaced-json.d.ts +0 -17
  70. package/src/utils/to-spaced-json.js +0 -27
@@ -0,0 +1,544 @@
1
+ import {expect} from 'chai';
2
+ import {format} from '@e22m4u/js-format';
3
+ import {OAOperationGroup} from './oa-operation-group.js';
4
+ import {OADocumentBuilder} from './oa-document-builder.js';
5
+
6
+ import {
7
+ OADataType,
8
+ OAOperationMethod,
9
+ OAParameterLocation,
10
+ } from './oa-specification.js';
11
+
12
+ describe('OAOperationGroup', function () {
13
+ describe('constructor', function () {
14
+ it('should require the parameter "builder" to be an instance of OADocumentBuilder', function () {
15
+ const throwable = v => () => new OAOperationGroup(v);
16
+ const error = s =>
17
+ format(
18
+ 'Parameter "builder" must be an instance of OADocumentBuilder, ' +
19
+ 'but %s was given.',
20
+ s,
21
+ );
22
+ expect(throwable('str')).to.throw(error('"str"'));
23
+ expect(throwable('')).to.throw(error('""'));
24
+ expect(throwable(10)).to.throw(error('10'));
25
+ expect(throwable(0)).to.throw(error('0'));
26
+ expect(throwable(true)).to.throw(error('true'));
27
+ expect(throwable(false)).to.throw(error('false'));
28
+ expect(throwable([])).to.throw(error('Array'));
29
+ expect(throwable({})).to.throw(error('Object'));
30
+ expect(throwable(undefined)).to.throw(error('undefined'));
31
+ expect(throwable(null)).to.throw(error('null'));
32
+ throwable(new OADocumentBuilder())();
33
+ });
34
+
35
+ it('should require the parameter "option" to be an Object', function () {
36
+ const builder = new OADocumentBuilder();
37
+ const throwable = v => () => new OAOperationGroup(builder, v);
38
+ const error = s =>
39
+ format('Parameter "options" must be an Object, but %s was given.', s);
40
+ expect(throwable('str')).to.throw(error('"str"'));
41
+ expect(throwable('')).to.throw(error('""'));
42
+ expect(throwable(10)).to.throw(error('10'));
43
+ expect(throwable(0)).to.throw(error('0'));
44
+ expect(throwable(true)).to.throw(error('true'));
45
+ expect(throwable(false)).to.throw(error('false'));
46
+ expect(throwable([])).to.throw(error('Array'));
47
+ expect(throwable(null)).to.throw(error('null'));
48
+ throwable({})();
49
+ throwable(undefined)();
50
+ });
51
+
52
+ it('should require the option "pathPrefix" to be a String', function () {
53
+ const builder = new OADocumentBuilder();
54
+ const throwable = v => () =>
55
+ new OAOperationGroup(builder, {pathPrefix: v});
56
+ const error = s =>
57
+ format('Option "pathPrefix" must be a String, but %s was given.', s);
58
+ expect(throwable(10)).to.throw(error('10'));
59
+ expect(throwable(0)).to.throw(error('0'));
60
+ expect(throwable(true)).to.throw(error('true'));
61
+ expect(throwable(false)).to.throw(error('false'));
62
+ expect(throwable([])).to.throw(error('Array'));
63
+ expect(throwable({})).to.throw(error('Object'));
64
+ expect(throwable(null)).to.throw(error('null'));
65
+ throwable('/')();
66
+ throwable(undefined)();
67
+ });
68
+
69
+ it('should require the option "pathPrefix" to start with a forward slash', function () {
70
+ const builder = new OADocumentBuilder();
71
+ const throwable = v => () =>
72
+ new OAOperationGroup(builder, {pathPrefix: v});
73
+ const error = s =>
74
+ format('Option "pathPrefix" must start with "/", but %s was given.', s);
75
+ expect(throwable('path')).to.throw(error('"path"'));
76
+ expect(throwable('')).to.throw(error('""'));
77
+ throwable('/path')();
78
+ throwable('/')();
79
+ });
80
+
81
+ it('should require the option "tags" to be an Array', function () {
82
+ const builder = new OADocumentBuilder();
83
+ const throwable = v => () => new OAOperationGroup(builder, {tags: v});
84
+ const error = s =>
85
+ format('Option "tags" must be an Array, but %s was given.', s);
86
+ expect(throwable('str')).to.throw(error('"str"'));
87
+ expect(throwable('')).to.throw(error('""'));
88
+ expect(throwable(10)).to.throw(error('10'));
89
+ expect(throwable(0)).to.throw(error('0'));
90
+ expect(throwable(true)).to.throw(error('true'));
91
+ expect(throwable(false)).to.throw(error('false'));
92
+ expect(throwable({})).to.throw(error('Object'));
93
+ expect(throwable(null)).to.throw(error('null'));
94
+ throwable([])();
95
+ throwable(undefined)();
96
+ });
97
+
98
+ it('should require elements in the option "tags" to be a non-empty String', function () {
99
+ const builder = new OADocumentBuilder();
100
+ const throwable = v => () => new OAOperationGroup(builder, {tags: [v]});
101
+ const error = s =>
102
+ format(
103
+ 'Element 0 in the option "tags" must be a non-empty String, ' +
104
+ 'but %s was given.',
105
+ s,
106
+ );
107
+ expect(throwable('')).to.throw(error('""'));
108
+ expect(throwable(10)).to.throw(error('10'));
109
+ expect(throwable(0)).to.throw(error('0'));
110
+ expect(throwable(true)).to.throw(error('true'));
111
+ expect(throwable(false)).to.throw(error('false'));
112
+ expect(throwable([])).to.throw(error('Array'));
113
+ expect(throwable({})).to.throw(error('Object'));
114
+ expect(throwable(null)).to.throw(error('null'));
115
+ throwable('str')();
116
+ });
117
+
118
+ it('should set a forward slash as the default path prefix', function () {
119
+ const builder = new OADocumentBuilder();
120
+ const S = new OAOperationGroup(builder);
121
+ expect(S.getPathPrefix()).to.be.eq('/');
122
+ });
123
+
124
+ it('should add the given path prefix to the group state', function () {
125
+ const builder = new OADocumentBuilder();
126
+ const S = new OAOperationGroup(builder, {pathPrefix: '/prefix'});
127
+ expect(S.getPathPrefix()).to.be.eq('/prefix');
128
+ });
129
+
130
+ it('should set an empty array as the default tags list', function () {
131
+ const builder = new OADocumentBuilder();
132
+ const S = new OAOperationGroup(builder);
133
+ expect(S.getTags()).to.be.eql([]);
134
+ });
135
+
136
+ it('should deduplicate the given tags list', function () {
137
+ const builder = new OADocumentBuilder();
138
+ const S = new OAOperationGroup(builder, {tags: ['foo', 'foo', 'bar']});
139
+ expect(S.getTags()).to.be.eql(['foo', 'bar']);
140
+ });
141
+ });
142
+
143
+ describe('getBuilder', function () {
144
+ it('should return an instance of the OADocumentBuilder', function () {
145
+ const builder = new OADocumentBuilder();
146
+ const S = new OAOperationGroup(builder);
147
+ expect(S.getBuilder()).to.be.eql(builder);
148
+ });
149
+ });
150
+
151
+ describe('getPathPrefix', function () {
152
+ it('should return a forward slash when no path prefix is specified', function () {
153
+ const builder = new OADocumentBuilder();
154
+ const S = new OAOperationGroup(builder);
155
+ expect(S.getPathPrefix()).to.be.eq('/');
156
+ });
157
+
158
+ it('should return the current path prefix', function () {
159
+ const builder = new OADocumentBuilder();
160
+ const S = new OAOperationGroup(builder, {pathPrefix: '/prefix'});
161
+ expect(S.getPathPrefix()).to.be.eq('/prefix');
162
+ });
163
+ });
164
+
165
+ describe('getTags', function () {
166
+ it('should return an empty array when no tags are specified', function () {
167
+ const builder = new OADocumentBuilder();
168
+ const S = new OAOperationGroup(builder);
169
+ expect(S.getTags()).to.be.eql([]);
170
+ });
171
+
172
+ it('should return a shallow copy of the current tags', function () {
173
+ const builder = new OADocumentBuilder();
174
+ const S = new OAOperationGroup(builder, {tags: ['foo', 'bar']});
175
+ const res1 = S.getTags();
176
+ const res2 = S.getTags();
177
+ expect(res1).to.be.eql(['foo', 'bar']);
178
+ expect(res1).to.be.not.eq(res2);
179
+ });
180
+ });
181
+
182
+ describe('defineOperation', function () {
183
+ it('should require the parameter "operationDef" to be an Object', function () {
184
+ const throwable = v => () => {
185
+ const builder = new OADocumentBuilder();
186
+ const S = new OAOperationGroup(builder);
187
+ S.defineOperation(v);
188
+ };
189
+ const error = s =>
190
+ format('Operation Definition must be an Object, but %s was given.', s);
191
+ expect(throwable('str')).to.throw(error('"str"'));
192
+ expect(throwable('')).to.throw(error('""'));
193
+ expect(throwable(10)).to.throw(error('10'));
194
+ expect(throwable(0)).to.throw(error('0'));
195
+ expect(throwable(true)).to.throw(error('true'));
196
+ expect(throwable(false)).to.throw(error('false'));
197
+ expect(throwable([])).to.throw(error('Array'));
198
+ expect(throwable(undefined)).to.throw(error('undefined'));
199
+ expect(throwable(null)).to.throw(error('null'));
200
+ throwable({
201
+ method: OAOperationMethod.GET,
202
+ path: '/path',
203
+ })();
204
+ });
205
+
206
+ it('should require the keyword "path" to be a String', function () {
207
+ const throwable = v => () => {
208
+ const builder = new OADocumentBuilder();
209
+ const S = new OAOperationGroup(builder);
210
+ S.defineOperation({
211
+ method: OAOperationMethod.POST,
212
+ path: v,
213
+ });
214
+ };
215
+ const error = s =>
216
+ format('Keyword "path" must be a String, but %s was given.', s);
217
+ expect(throwable(10)).to.throw(error('10'));
218
+ expect(throwable(0)).to.throw(error('0'));
219
+ expect(throwable(true)).to.throw(error('true'));
220
+ expect(throwable(false)).to.throw(error('false'));
221
+ expect(throwable([])).to.throw(error('Array'));
222
+ expect(throwable(undefined)).to.throw(error('undefined'));
223
+ expect(throwable(null)).to.throw(error('null'));
224
+ throwable('/path')();
225
+ });
226
+
227
+ it('should require the keyword "path" to start with a forward slash', function () {
228
+ const throwable = v => () => {
229
+ const builder = new OADocumentBuilder();
230
+ const S = new OAOperationGroup(builder);
231
+ S.defineOperation({
232
+ method: OAOperationMethod.POST,
233
+ path: v,
234
+ });
235
+ };
236
+ const error = s =>
237
+ format('Keyword "path" must start with "/", but %s was given.', s);
238
+ expect(throwable('path')).to.throw(error('"path"'));
239
+ expect(throwable('')).to.throw(error('""'));
240
+ throwable('/path')();
241
+ throwable('/')();
242
+ });
243
+
244
+ it('should require the keyword "method" to be a correct value', function () {
245
+ const throwable = v => () => {
246
+ const builder = new OADocumentBuilder();
247
+ const S = new OAOperationGroup(builder);
248
+ S.defineOperation({
249
+ method: v,
250
+ path: '/',
251
+ });
252
+ };
253
+ const error = s =>
254
+ format(
255
+ 'Keyword "method" must be one of the allowed values, ' +
256
+ 'but %s was given.',
257
+ s,
258
+ );
259
+ expect(throwable('str')).to.throw(error('"str"'));
260
+ expect(throwable('')).to.throw(error('""'));
261
+ expect(throwable(10)).to.throw(error('10'));
262
+ expect(throwable(0)).to.throw(error('0'));
263
+ expect(throwable(true)).to.throw(error('true'));
264
+ expect(throwable(false)).to.throw(error('false'));
265
+ expect(throwable([])).to.throw(error('Array'));
266
+ expect(throwable(undefined)).to.throw(error('undefined'));
267
+ expect(throwable(null)).to.throw(error('null'));
268
+ Object.values(OAOperationMethod).forEach(method => {
269
+ throwable(method)();
270
+ });
271
+ });
272
+
273
+ it('should require the keyword "operation" to be an Object', function () {
274
+ const throwable = v => () => {
275
+ const builder = new OADocumentBuilder();
276
+ const S = new OAOperationGroup(builder);
277
+ S.defineOperation({
278
+ method: OAOperationMethod.GET,
279
+ path: '/',
280
+ operation: v,
281
+ });
282
+ };
283
+ const error = s =>
284
+ format('Keyword "operation" must be an Object, but %s was given.', s);
285
+ expect(throwable('str')).to.throw(error('"str"'));
286
+ expect(throwable('')).to.throw(error('""'));
287
+ expect(throwable(10)).to.throw(error('10'));
288
+ expect(throwable(0)).to.throw(error('0'));
289
+ expect(throwable(true)).to.throw(error('true'));
290
+ expect(throwable(false)).to.throw(error('false'));
291
+ expect(throwable([])).to.throw(error('Array'));
292
+ expect(throwable(null)).to.throw(error('null'));
293
+ throwable({})();
294
+ throwable(undefined)();
295
+ });
296
+
297
+ it('should define operation in the document builder', function () {
298
+ const builder = new OADocumentBuilder();
299
+ const S = new OAOperationGroup(builder);
300
+ const operation = {
301
+ parameters: [
302
+ {
303
+ name: 'id',
304
+ in: OAParameterLocation.QUERY,
305
+ schema: {type: OADataType.STRING},
306
+ },
307
+ ],
308
+ };
309
+ S.defineOperation({
310
+ method: OAOperationMethod.POST,
311
+ path: '/create',
312
+ operation,
313
+ });
314
+ const doc = builder.getDocumentObjectRef();
315
+ expect(doc.paths['/create'].post).to.be.eql(operation);
316
+ });
317
+
318
+ it('should add the path prefix to the operation path', function () {
319
+ const builder = new OADocumentBuilder();
320
+ const S = new OAOperationGroup(builder, {pathPrefix: '/prefix'});
321
+ S.defineOperation({
322
+ method: OAOperationMethod.GET,
323
+ path: '/path',
324
+ });
325
+ const res = builder.getDocumentObjectRef();
326
+ expect(res.paths['/prefix/path'].get).to.be.an('object');
327
+ });
328
+
329
+ it('should ignore the path prefix with a forward slash only', function () {
330
+ const builder = new OADocumentBuilder();
331
+ const S = new OAOperationGroup(builder, {pathPrefix: '/'});
332
+ S.defineOperation({
333
+ method: OAOperationMethod.GET,
334
+ path: '/path',
335
+ });
336
+ const res = builder.getDocumentObjectRef();
337
+ expect(res.paths['/path'].get).to.be.an('object');
338
+ });
339
+
340
+ it('should ignore the operation path with a forward slash only', function () {
341
+ const builder = new OADocumentBuilder();
342
+ const S = new OAOperationGroup(builder, {pathPrefix: '/prefix'});
343
+ S.defineOperation({
344
+ method: OAOperationMethod.GET,
345
+ path: '/',
346
+ });
347
+ const res = builder.getDocumentObjectRef();
348
+ expect(res.paths['/prefix'].get).to.be.an('object');
349
+ });
350
+
351
+ it('should add the group tags to the operation object', function () {
352
+ const builder = new OADocumentBuilder();
353
+ const S = new OAOperationGroup(builder, {tags: ['foo', 'bar']});
354
+ S.defineOperation({
355
+ method: OAOperationMethod.GET,
356
+ path: '/path',
357
+ });
358
+ const res = builder.getDocumentObjectRef();
359
+ expect(res.paths['/path'].get.tags).to.be.eql(['foo', 'bar']);
360
+ });
361
+
362
+ it('should merge the operation tags with the group tags', function () {
363
+ const builder = new OADocumentBuilder();
364
+ const S = new OAOperationGroup(builder, {tags: ['foo']});
365
+ S.defineOperation({
366
+ method: OAOperationMethod.GET,
367
+ path: '/path',
368
+ operation: {tags: ['bar']},
369
+ });
370
+ const res = builder.getDocumentObjectRef();
371
+ expect(res.paths['/path'].get.tags).to.be.eql(['foo', 'bar']);
372
+ });
373
+
374
+ it('should ignore the group tags existed in the operation object', function () {
375
+ const builder = new OADocumentBuilder();
376
+ const S = new OAOperationGroup(builder, {tags: ['foo', 'bar']});
377
+ S.defineOperation({
378
+ method: OAOperationMethod.GET,
379
+ path: '/path',
380
+ operation: {tags: ['bar', 'baz']},
381
+ });
382
+ const res = builder.getDocumentObjectRef();
383
+ expect(res.paths['/path'].get.tags).to.be.eql(['foo', 'bar', 'baz']);
384
+ });
385
+
386
+ it('should return itself', function () {
387
+ const builder = new OADocumentBuilder();
388
+ const S = new OAOperationGroup(builder);
389
+ const res = S.defineOperation({
390
+ method: OAOperationMethod.GET,
391
+ path: '/path',
392
+ operation: {tags: ['bar', 'baz']},
393
+ });
394
+ expect(res).to.be.eq(S);
395
+ });
396
+ });
397
+
398
+ describe('createOperationGroup', function () {
399
+ it('should require the parameter "option" to be an Object', function () {
400
+ const builder = new OADocumentBuilder();
401
+ const throwable = v => () => {
402
+ const S = new OAOperationGroup(builder);
403
+ S.createOperationGroup(v);
404
+ };
405
+ const error = s =>
406
+ format('Parameter "options" must be an Object, but %s was given.', s);
407
+ expect(throwable('str')).to.throw(error('"str"'));
408
+ expect(throwable('')).to.throw(error('""'));
409
+ expect(throwable(10)).to.throw(error('10'));
410
+ expect(throwable(0)).to.throw(error('0'));
411
+ expect(throwable(true)).to.throw(error('true'));
412
+ expect(throwable(false)).to.throw(error('false'));
413
+ expect(throwable([])).to.throw(error('Array'));
414
+ expect(throwable(null)).to.throw(error('null'));
415
+ throwable({})();
416
+ throwable(undefined)();
417
+ });
418
+
419
+ it('should require the option "pathPrefix" to be a String', function () {
420
+ const builder = new OADocumentBuilder();
421
+ const throwable = v => () => {
422
+ const S = new OAOperationGroup(builder);
423
+ S.createOperationGroup({pathPrefix: v});
424
+ };
425
+ const error = s =>
426
+ format('Option "pathPrefix" must be a String, but %s was given.', s);
427
+ expect(throwable(10)).to.throw(error('10'));
428
+ expect(throwable(0)).to.throw(error('0'));
429
+ expect(throwable(true)).to.throw(error('true'));
430
+ expect(throwable(false)).to.throw(error('false'));
431
+ expect(throwable([])).to.throw(error('Array'));
432
+ expect(throwable({})).to.throw(error('Object'));
433
+ expect(throwable(null)).to.throw(error('null'));
434
+ throwable('/')();
435
+ throwable(undefined)();
436
+ });
437
+
438
+ it('should require the option "pathPrefix" to start with a forward slash', function () {
439
+ const builder = new OADocumentBuilder();
440
+ const throwable = v => () => {
441
+ const S = new OAOperationGroup(builder);
442
+ S.createOperationGroup({pathPrefix: v});
443
+ };
444
+ const error = s =>
445
+ format('Option "pathPrefix" must start with "/", but %s was given.', s);
446
+ expect(throwable('path')).to.throw(error('"path"'));
447
+ expect(throwable('')).to.throw(error('""'));
448
+ throwable('/path')();
449
+ throwable('/')();
450
+ });
451
+
452
+ it('should require the option "tags" to be an Array', function () {
453
+ const builder = new OADocumentBuilder();
454
+ const throwable = v => () => {
455
+ const S = new OAOperationGroup(builder);
456
+ S.createOperationGroup({tags: v});
457
+ };
458
+ const error = s =>
459
+ format('Option "tags" must be an Array, but %s was given.', s);
460
+ expect(throwable('str')).to.throw(error('"str"'));
461
+ expect(throwable('')).to.throw(error('""'));
462
+ expect(throwable(10)).to.throw(error('10'));
463
+ expect(throwable(0)).to.throw(error('0'));
464
+ expect(throwable(true)).to.throw(error('true'));
465
+ expect(throwable(false)).to.throw(error('false'));
466
+ expect(throwable({})).to.throw(error('Object'));
467
+ expect(throwable(null)).to.throw(error('null'));
468
+ throwable([])();
469
+ throwable(undefined)();
470
+ });
471
+
472
+ it('should require elements in the option "tags" to be a non-empty String', function () {
473
+ const builder = new OADocumentBuilder();
474
+ const throwable = v => () => {
475
+ const S = new OAOperationGroup(builder);
476
+ S.createOperationGroup({tags: [v]});
477
+ };
478
+ const error = s =>
479
+ format(
480
+ 'Element 0 in the option "tags" must be a non-empty String, ' +
481
+ 'but %s was given.',
482
+ s,
483
+ );
484
+ expect(throwable('')).to.throw(error('""'));
485
+ expect(throwable(10)).to.throw(error('10'));
486
+ expect(throwable(0)).to.throw(error('0'));
487
+ expect(throwable(true)).to.throw(error('true'));
488
+ expect(throwable(false)).to.throw(error('false'));
489
+ expect(throwable([])).to.throw(error('Array'));
490
+ expect(throwable({})).to.throw(error('Object'));
491
+ expect(throwable(null)).to.throw(error('null'));
492
+ throwable('str')();
493
+ });
494
+
495
+ it('should add the current path prefix to the new group', function () {
496
+ const builder = new OADocumentBuilder();
497
+ const S = new OAOperationGroup(builder, {pathPrefix: '/prefix'});
498
+ const res = S.createOperationGroup();
499
+ expect(res.getPathPrefix()).to.be.eq('/prefix');
500
+ });
501
+
502
+ it('should prepend the current path prefix to the new prefix', function () {
503
+ const builder = new OADocumentBuilder();
504
+ const S = new OAOperationGroup(builder, {pathPrefix: '/a'});
505
+ const res = S.createOperationGroup({pathPrefix: '/b'});
506
+ expect(res.getPathPrefix()).to.be.eq('/a/b');
507
+ });
508
+
509
+ it('should ignore the current path prefix with a forward slash only', function () {
510
+ const builder = new OADocumentBuilder();
511
+ const S = new OAOperationGroup(builder, {pathPrefix: '/'});
512
+ const res = S.createOperationGroup({pathPrefix: '/prefix'});
513
+ expect(res.getPathPrefix()).to.be.eq('/prefix');
514
+ });
515
+
516
+ it('should ignore the new path prefix with a forward slash only', function () {
517
+ const builder = new OADocumentBuilder();
518
+ const S = new OAOperationGroup(builder, {pathPrefix: '/prefix'});
519
+ const res = S.createOperationGroup({pathPrefix: '/'});
520
+ expect(res.getPathPrefix()).to.be.eq('/prefix');
521
+ });
522
+
523
+ it('should add the current tags to the new group', function () {
524
+ const builder = new OADocumentBuilder();
525
+ const S = new OAOperationGroup(builder, {tags: ['foo', 'bar']});
526
+ const res = S.createOperationGroup();
527
+ expect(res.getTags()).to.be.eql(['foo', 'bar']);
528
+ });
529
+
530
+ it('should merge the current tags with the new tags', function () {
531
+ const builder = new OADocumentBuilder();
532
+ const S = new OAOperationGroup(builder, {tags: ['foo']});
533
+ const res = S.createOperationGroup({tags: ['bar']});
534
+ expect(res.getTags()).to.be.eql(['foo', 'bar']);
535
+ });
536
+
537
+ it('should ignore the current tags existed in the new tags', function () {
538
+ const builder = new OADocumentBuilder();
539
+ const S = new OAOperationGroup(builder, {tags: ['foo', 'bar']});
540
+ const res = S.createOperationGroup({tags: ['bar', 'baz']});
541
+ expect(res.getTags()).to.be.eql(['foo', 'bar', 'baz']);
542
+ });
543
+ });
544
+ });
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export function isOAReferenceObject(value) {
8
8
  if (value && typeof value === 'object' && !Array.isArray(value)) {
9
- if (value.$ref !== undefined || value.$dynamicRef !== undefined) {
9
+ if (value.$ref !== undefined) {
10
10
  return true;
11
11
  }
12
12
  }
@@ -14,6 +14,6 @@ describe('isOAReferenceObject', function () {
14
14
  expect(isOAReferenceObject(undefined)).to.be.false;
15
15
  expect(isOAReferenceObject(null)).to.be.false;
16
16
  expect(isOAReferenceObject({$ref: '123'})).to.be.true;
17
- expect(isOAReferenceObject({$dynamicRef: '123'})).to.be.true;
17
+ expect(isOAReferenceObject({$dynamicRef: '123'})).to.be.false;
18
18
  });
19
19
  });
@@ -1,5 +1,6 @@
1
1
  import {InvalidArgumentError} from '@e22m4u/js-format';
2
2
  import {escapeJsonPointer} from '../json-pointer/index.js';
3
+ import {OA_COMPONENT_NAME_REGEX} from '../oa-document-builder.js';
3
4
 
4
5
  /**
5
6
  * Create the Reference Object.
@@ -15,6 +16,12 @@ function oaRef(name, segment) {
15
16
  name,
16
17
  );
17
18
  }
19
+ if (!OA_COMPONENT_NAME_REGEX.test(name)) {
20
+ throw new InvalidArgumentError(
21
+ 'Component name %v contains invalid characters.',
22
+ name,
23
+ );
24
+ }
18
25
  const escapedName = escapeJsonPointer(name);
19
26
  return {$ref: `#/components/${segment}/${escapedName}`};
20
27
  }
@@ -7,8 +7,7 @@ import {resolveJsonPointer} from '../json-pointer/index.js';
7
7
  * документа `options.rootDocument`. Утилита находит и возвращает узел, на который
8
8
  * указывает `$ref`.
9
9
  *
10
- * - Поддерживает только локальные ссылки, начинающиеся с `#`.
11
- * - Нет поддержки $dynamicRef, $anchor и $id.
10
+ * Поддерживает только локальные ссылки, начинающиеся с `#`.
12
11
  *
13
12
  * @param {object} referenceObj
14
13
  * @param {object} [options]
@@ -96,15 +95,6 @@ export function resolveOAReferenceObject(referenceObj, options = {}) {
96
95
  refUri,
97
96
  );
98
97
  }
99
- // $dynamicRef
100
- if (referenceObj.$dynamicRef) {
101
- // поддержка $dynamicRef требует реализации динамической области
102
- // видимости с отслеживанием стека вызовов при обходе схемы,
103
- // но данная утилитарная функция выполняется без контекста
104
- throw new InvalidArgumentError(
105
- 'Schema keyword "$dynamicRef" is not supported.',
106
- );
107
- }
108
98
  // если объект ссылки не имеет свойств
109
99
  // указателей, то выбрасывается ошибка
110
100
  throw new InvalidArgumentError(
@@ -220,14 +220,4 @@ describe('resolveOAReferenceObject', function () {
220
220
  });
221
221
  });
222
222
  });
223
-
224
- describe('$dynamicRef', function () {
225
- it('should throw an error when a dynamic reference is provided', function () {
226
- const throwable = () =>
227
- resolveOAReferenceObject({$dynamicRef: '#meta'}, {rootDocument: {}});
228
- expect(throwable).to.throw(
229
- 'Schema keyword "$dynamicRef" is not supported.',
230
- );
231
- });
232
- });
233
223
  });