@redocly/openapi-core 1.0.0-beta.125 → 1.0.0-beta.127

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 (281) hide show
  1. package/lib/bundle.js +5 -2
  2. package/lib/config/all.js +8 -1
  3. package/lib/resolve.js +5 -1
  4. package/lib/rules/common/required-string-property-missing-min-length.d.ts +1 -1
  5. package/lib/rules/common/required-string-property-missing-min-length.js +3 -3
  6. package/lib/rules/common/spec.js +1 -0
  7. package/lib/rules/oas2/index.js +1 -1
  8. package/lib/rules/oas2/request-mime-type.d.ts +1 -1
  9. package/lib/rules/oas2/response-mime-type.d.ts +1 -1
  10. package/lib/rules/oas3/index.js +1 -1
  11. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.d.ts +2 -2
  12. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.js +3 -3
  13. package/lib/rules/oas3/request-mime-type.d.ts +1 -1
  14. package/lib/rules/oas3/response-mime-type.d.ts +1 -1
  15. package/lib/walk.d.ts +6 -5
  16. package/lib/walk.js +23 -27
  17. package/package.json +1 -1
  18. package/__tests__/utils.ts +0 -88
  19. package/src/__tests__/__snapshots__/bundle.test.ts.snap +0 -437
  20. package/src/__tests__/bundle.test.ts +0 -236
  21. package/src/__tests__/codeframes.test.ts +0 -530
  22. package/src/__tests__/fixtures/.redocly.lint-ignore.yaml +0 -5
  23. package/src/__tests__/fixtures/extension.js +0 -24
  24. package/src/__tests__/fixtures/refs/definitions.yaml +0 -3
  25. package/src/__tests__/fixtures/refs/examples.yaml +0 -8
  26. package/src/__tests__/fixtures/refs/external-request-body.yaml +0 -13
  27. package/src/__tests__/fixtures/refs/externalref.yaml +0 -35
  28. package/src/__tests__/fixtures/refs/hosted.yaml +0 -35
  29. package/src/__tests__/fixtures/refs/openapi-with-external-refs-conflicting-names.yaml +0 -21
  30. package/src/__tests__/fixtures/refs/openapi-with-external-refs.yaml +0 -33
  31. package/src/__tests__/fixtures/refs/openapi-with-url-refs.yaml +0 -18
  32. package/src/__tests__/fixtures/refs/param-b.yaml +0 -1
  33. package/src/__tests__/fixtures/refs/param-c.yaml +0 -1
  34. package/src/__tests__/fixtures/refs/rename.yaml +0 -1
  35. package/src/__tests__/fixtures/refs/requestBody.yaml +0 -9
  36. package/src/__tests__/fixtures/refs/schema-a.yaml +0 -1
  37. package/src/__tests__/fixtures/refs/simple.yaml +0 -1
  38. package/src/__tests__/fixtures/refs/vendor.schema.yaml +0 -20
  39. package/src/__tests__/fixtures/resolve/External.yaml +0 -10
  40. package/src/__tests__/fixtures/resolve/External2.yaml +0 -4
  41. package/src/__tests__/fixtures/resolve/description.md +0 -3
  42. package/src/__tests__/fixtures/resolve/externalInfo.yaml +0 -4
  43. package/src/__tests__/fixtures/resolve/externalLicense.yaml +0 -1
  44. package/src/__tests__/fixtures/resolve/openapi-with-back.yaml +0 -13
  45. package/src/__tests__/fixtures/resolve/openapi-with-md-description.yaml +0 -5
  46. package/src/__tests__/fixtures/resolve/openapi.yaml +0 -28
  47. package/src/__tests__/fixtures/resolve/schemas/type-a.yaml +0 -10
  48. package/src/__tests__/fixtures/resolve/schemas/type-b.yaml +0 -6
  49. package/src/__tests__/fixtures/resolve/transitive/a.yaml +0 -1
  50. package/src/__tests__/fixtures/resolve/transitive/components.yaml +0 -5
  51. package/src/__tests__/fixtures/resolve/transitive/schemas.yaml +0 -3
  52. package/src/__tests__/format.test.ts +0 -76
  53. package/src/__tests__/js-yaml.test.ts +0 -73
  54. package/src/__tests__/lint.test.ts +0 -388
  55. package/src/__tests__/logger-browser.test.ts +0 -53
  56. package/src/__tests__/logger.test.ts +0 -47
  57. package/src/__tests__/login.test.ts +0 -17
  58. package/src/__tests__/normalizeVisitors.test.ts +0 -151
  59. package/src/__tests__/output-browser.test.ts +0 -18
  60. package/src/__tests__/output.test.ts +0 -15
  61. package/src/__tests__/ref-utils.test.ts +0 -120
  62. package/src/__tests__/resolve-http.test.ts +0 -77
  63. package/src/__tests__/resolve.test.ts +0 -408
  64. package/src/__tests__/utils-browser.test.ts +0 -11
  65. package/src/__tests__/utils.test.ts +0 -144
  66. package/src/__tests__/walk.test.ts +0 -1545
  67. package/src/benchmark/benches/lint-with-many-rules.bench.ts +0 -35
  68. package/src/benchmark/benches/lint-with-nested-rule.bench.ts +0 -39
  69. package/src/benchmark/benches/lint-with-no-rules.bench.ts +0 -20
  70. package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +0 -35
  71. package/src/benchmark/benches/lint-with-top-level-rule.bench.ts +0 -32
  72. package/src/benchmark/benches/rebilly.yaml +0 -32275
  73. package/src/benchmark/benches/recommended-oas3.bench.ts +0 -22
  74. package/src/benchmark/benches/resolve-with-no-external.bench.ts +0 -23
  75. package/src/benchmark/benchmark.js +0 -311
  76. package/src/benchmark/colors.js +0 -29
  77. package/src/benchmark/fork.js +0 -83
  78. package/src/benchmark/utils.ts +0 -36
  79. package/src/bundle.ts +0 -399
  80. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +0 -161
  81. package/src/config/__tests__/__snapshots__/config.test.ts.snap +0 -144
  82. package/src/config/__tests__/config-resolvers.test.ts +0 -491
  83. package/src/config/__tests__/config.test.ts +0 -307
  84. package/src/config/__tests__/fixtures/ingore-file.ts +0 -8
  85. package/src/config/__tests__/fixtures/load-redocly.yaml +0 -2
  86. package/src/config/__tests__/fixtures/plugin-config.yaml +0 -2
  87. package/src/config/__tests__/fixtures/plugin.js +0 -56
  88. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +0 -11
  89. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +0 -69
  90. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +0 -7
  91. package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +0 -17
  92. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +0 -18
  93. package/src/config/__tests__/fixtures/resolve-config/local-config-with-wrong-custom-function.yaml +0 -15
  94. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +0 -9
  95. package/src/config/__tests__/fixtures/resolve-config/plugin.js +0 -80
  96. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +0 -3
  97. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +0 -4
  98. package/src/config/__tests__/load.test.ts +0 -167
  99. package/src/config/__tests__/resolve-plugins.test.ts +0 -27
  100. package/src/config/__tests__/utils.test.ts +0 -204
  101. package/src/config/all.ts +0 -66
  102. package/src/config/builtIn.ts +0 -37
  103. package/src/config/config-resolvers.ts +0 -465
  104. package/src/config/config.ts +0 -330
  105. package/src/config/index.ts +0 -7
  106. package/src/config/load.ts +0 -144
  107. package/src/config/minimal.ts +0 -60
  108. package/src/config/recommended.ts +0 -60
  109. package/src/config/rules.ts +0 -54
  110. package/src/config/types.ts +0 -216
  111. package/src/config/utils.ts +0 -333
  112. package/src/decorators/__tests__/filter-in.test.ts +0 -310
  113. package/src/decorators/__tests__/filter-out.test.ts +0 -335
  114. package/src/decorators/__tests__/media-type-examples-override.test.ts +0 -665
  115. package/src/decorators/__tests__/remove-x-internal.test.ts +0 -316
  116. package/src/decorators/__tests__/resources/request.yaml +0 -3
  117. package/src/decorators/__tests__/resources/response.yaml +0 -3
  118. package/src/decorators/common/filters/filter-helper.ts +0 -72
  119. package/src/decorators/common/filters/filter-in.ts +0 -18
  120. package/src/decorators/common/filters/filter-out.ts +0 -18
  121. package/src/decorators/common/info-description-override.ts +0 -24
  122. package/src/decorators/common/info-override.ts +0 -15
  123. package/src/decorators/common/media-type-examples-override.ts +0 -79
  124. package/src/decorators/common/operation-description-override.ts +0 -30
  125. package/src/decorators/common/registry-dependencies.ts +0 -25
  126. package/src/decorators/common/remove-x-internal.ts +0 -59
  127. package/src/decorators/common/tag-description-override.ts +0 -25
  128. package/src/decorators/oas2/index.ts +0 -20
  129. package/src/decorators/oas3/index.ts +0 -22
  130. package/src/env.ts +0 -5
  131. package/src/format/codeframes.ts +0 -216
  132. package/src/format/format.ts +0 -375
  133. package/src/index.ts +0 -71
  134. package/src/js-yaml/index.ts +0 -14
  135. package/src/lint.ts +0 -130
  136. package/src/logger.ts +0 -34
  137. package/src/oas-types.ts +0 -57
  138. package/src/output.ts +0 -7
  139. package/src/redocly/__tests__/redocly-client.test.ts +0 -146
  140. package/src/redocly/index.ts +0 -187
  141. package/src/redocly/redocly-client-types.ts +0 -10
  142. package/src/redocly/registry-api-types.ts +0 -32
  143. package/src/redocly/registry-api.ts +0 -149
  144. package/src/ref-utils.ts +0 -85
  145. package/src/resolve.ts +0 -412
  146. package/src/rules/__tests__/fixtures/code-sample.php +0 -9
  147. package/src/rules/__tests__/fixtures/invalid-yaml.yaml +0 -1
  148. package/src/rules/__tests__/fixtures/ref.yaml +0 -1
  149. package/src/rules/__tests__/no-unresolved-refs.test.ts +0 -257
  150. package/src/rules/__tests__/utils.test.ts +0 -160
  151. package/src/rules/ajv.ts +0 -102
  152. package/src/rules/common/__tests__/info-license.test.ts +0 -62
  153. package/src/rules/common/__tests__/license-url.test.ts +0 -63
  154. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +0 -96
  155. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +0 -210
  156. package/src/rules/common/__tests__/no-identical-paths.test.ts +0 -58
  157. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +0 -85
  158. package/src/rules/common/__tests__/operation-2xx-response.test.ts +0 -192
  159. package/src/rules/common/__tests__/operation-4xx-response.test.ts +0 -231
  160. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +0 -76
  161. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +0 -45
  162. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +0 -167
  163. package/src/rules/common/__tests__/operation-singular-tag.test.ts +0 -72
  164. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +0 -95
  165. package/src/rules/common/__tests__/path-not-include-query.test.ts +0 -64
  166. package/src/rules/common/__tests__/path-params-defined.test.ts +0 -202
  167. package/src/rules/common/__tests__/paths-kebab-case.test.ts +0 -108
  168. package/src/rules/common/__tests__/scalar-property-missing-example.test.ts +0 -264
  169. package/src/rules/common/__tests__/security-defined.test.ts +0 -175
  170. package/src/rules/common/__tests__/spec.test.ts +0 -555
  171. package/src/rules/common/__tests__/tag-description.test.ts +0 -65
  172. package/src/rules/common/__tests__/tags-alphabetical.test.ts +0 -64
  173. package/src/rules/common/assertions/__tests__/asserts.test.ts +0 -869
  174. package/src/rules/common/assertions/__tests__/index.test.ts +0 -100
  175. package/src/rules/common/assertions/__tests__/utils.test.ts +0 -236
  176. package/src/rules/common/assertions/asserts.ts +0 -357
  177. package/src/rules/common/assertions/index.ts +0 -56
  178. package/src/rules/common/assertions/utils.ts +0 -331
  179. package/src/rules/common/info-contact.ts +0 -15
  180. package/src/rules/common/info-license-url.ts +0 -10
  181. package/src/rules/common/info-license.ts +0 -15
  182. package/src/rules/common/no-ambiguous-paths.ts +0 -50
  183. package/src/rules/common/no-enum-type-mismatch.ts +0 -52
  184. package/src/rules/common/no-http-verbs-in-paths.ts +0 -36
  185. package/src/rules/common/no-identical-paths.ts +0 -24
  186. package/src/rules/common/no-invalid-parameter-examples.ts +0 -36
  187. package/src/rules/common/no-invalid-schema-examples.ts +0 -27
  188. package/src/rules/common/no-path-trailing-slash.ts +0 -15
  189. package/src/rules/common/operation-2xx-response.ts +0 -24
  190. package/src/rules/common/operation-4xx-response.ts +0 -24
  191. package/src/rules/common/operation-description.ts +0 -13
  192. package/src/rules/common/operation-operationId-unique.ts +0 -21
  193. package/src/rules/common/operation-operationId-url-safe.ts +0 -19
  194. package/src/rules/common/operation-operationId.ts +0 -17
  195. package/src/rules/common/operation-parameters-unique.ts +0 -48
  196. package/src/rules/common/operation-singular-tag.ts +0 -17
  197. package/src/rules/common/operation-summary.ts +0 -13
  198. package/src/rules/common/operation-tag-defined.ts +0 -26
  199. package/src/rules/common/parameter-description.ts +0 -22
  200. package/src/rules/common/path-declaration-must-exist.ts +0 -15
  201. package/src/rules/common/path-excludes-patterns.ts +0 -23
  202. package/src/rules/common/path-http-verbs-order.ts +0 -30
  203. package/src/rules/common/path-not-include-query.ts +0 -17
  204. package/src/rules/common/path-params-defined.ts +0 -65
  205. package/src/rules/common/path-segment-plural.ts +0 -31
  206. package/src/rules/common/paths-kebab-case.ts +0 -19
  207. package/src/rules/common/required-string-property-missing-min-length.ts +0 -44
  208. package/src/rules/common/response-contains-header.ts +0 -35
  209. package/src/rules/common/scalar-property-missing-example.ts +0 -58
  210. package/src/rules/common/security-defined.ts +0 -65
  211. package/src/rules/common/spec.ts +0 -174
  212. package/src/rules/common/tag-description.ts +0 -10
  213. package/src/rules/common/tags-alphabetical.ts +0 -20
  214. package/src/rules/no-unresolved-refs.ts +0 -51
  215. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +0 -110
  216. package/src/rules/oas2/__tests__/response-contains-header.test.ts +0 -174
  217. package/src/rules/oas2/__tests__/response-contains-property.test.ts +0 -155
  218. package/src/rules/oas2/__tests__/spec/fixtures/description.md +0 -1
  219. package/src/rules/oas2/__tests__/spec/info.test.ts +0 -355
  220. package/src/rules/oas2/__tests__/spec/operation.test.ts +0 -123
  221. package/src/rules/oas2/__tests__/spec/paths.test.ts +0 -245
  222. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +0 -35
  223. package/src/rules/oas2/__tests__/spec/utils.ts +0 -32
  224. package/src/rules/oas2/boolean-parameter-prefixes.ts +0 -26
  225. package/src/rules/oas2/index.ts +0 -89
  226. package/src/rules/oas2/remove-unused-components.ts +0 -81
  227. package/src/rules/oas2/request-mime-type.ts +0 -17
  228. package/src/rules/oas2/response-contains-property.ts +0 -36
  229. package/src/rules/oas2/response-mime-type.ts +0 -17
  230. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +0 -111
  231. package/src/rules/oas3/__tests__/fixtures/common.yaml +0 -11
  232. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +0 -205
  233. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +0 -65
  234. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +0 -473
  235. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +0 -60
  236. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +0 -79
  237. package/src/rules/oas3/__tests__/no-unused-components.test.ts +0 -131
  238. package/src/rules/oas3/__tests__/operation-4xx-problem-details-rfc7807.test.ts +0 -145
  239. package/src/rules/oas3/__tests__/response-contains-header.test.ts +0 -389
  240. package/src/rules/oas3/__tests__/response-contains-property.test.ts +0 -403
  241. package/src/rules/oas3/__tests__/spec/callbacks.test.ts +0 -41
  242. package/src/rules/oas3/__tests__/spec/fixtures/description.md +0 -1
  243. package/src/rules/oas3/__tests__/spec/info.test.ts +0 -391
  244. package/src/rules/oas3/__tests__/spec/operation.test.ts +0 -253
  245. package/src/rules/oas3/__tests__/spec/paths.test.ts +0 -284
  246. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +0 -77
  247. package/src/rules/oas3/__tests__/spec/servers.test.ts +0 -505
  248. package/src/rules/oas3/__tests__/spec/spec.test.ts +0 -298
  249. package/src/rules/oas3/__tests__/spec/utils.ts +0 -32
  250. package/src/rules/oas3/__tests__/spec-components-invalid-map-name.test.ts +0 -305
  251. package/src/rules/oas3/boolean-parameter-prefixes.ts +0 -28
  252. package/src/rules/oas3/index.ts +0 -109
  253. package/src/rules/oas3/no-empty-servers.ts +0 -22
  254. package/src/rules/oas3/no-example-value-and-externalValue.ts +0 -14
  255. package/src/rules/oas3/no-invalid-media-type-examples.ts +0 -49
  256. package/src/rules/oas3/no-server-example.com.ts +0 -14
  257. package/src/rules/oas3/no-server-trailing-slash.ts +0 -15
  258. package/src/rules/oas3/no-server-variables-empty-enum.ts +0 -66
  259. package/src/rules/oas3/no-undefined-server-variable.ts +0 -30
  260. package/src/rules/oas3/no-unused-components.ts +0 -75
  261. package/src/rules/oas3/operation-4xx-problem-details-rfc7807.ts +0 -36
  262. package/src/rules/oas3/remove-unused-components.ts +0 -95
  263. package/src/rules/oas3/request-mime-type.ts +0 -31
  264. package/src/rules/oas3/response-contains-property.ts +0 -38
  265. package/src/rules/oas3/response-mime-type.ts +0 -31
  266. package/src/rules/oas3/spec-components-invalid-map-name.ts +0 -74
  267. package/src/rules/other/stats.ts +0 -73
  268. package/src/rules/utils.ts +0 -191
  269. package/src/types/index.ts +0 -149
  270. package/src/types/oas2.ts +0 -478
  271. package/src/types/oas3.ts +0 -597
  272. package/src/types/oas3_1.ts +0 -258
  273. package/src/types/redocly-yaml.ts +0 -1010
  274. package/src/typings/common.ts +0 -17
  275. package/src/typings/openapi.ts +0 -298
  276. package/src/typings/swagger.ts +0 -236
  277. package/src/utils.ts +0 -276
  278. package/src/visitors.ts +0 -491
  279. package/src/walk.ts +0 -453
  280. package/tsconfig.json +0 -8
  281. package/tsconfig.tsbuildinfo +0 -1
@@ -1,1545 +0,0 @@
1
- import outdent from 'outdent';
2
- import each from 'jest-each';
3
- import * as path from 'path';
4
-
5
- import { lintDocument } from '../lint';
6
-
7
- import {
8
- parseYamlToDocument,
9
- replaceSourceWithRef,
10
- makeConfigForRuleset,
11
- } from '../../__tests__/utils';
12
- import { BaseResolver, Document } from '../resolve';
13
- import { listOf } from '../types';
14
- import { Oas3RuleSet } from '../oas-types';
15
-
16
- describe('walk order', () => {
17
- it('should run visitors', async () => {
18
- const visitors = {
19
- Root: {
20
- enter: jest.fn(),
21
- leave: jest.fn(),
22
- },
23
- Info: {
24
- enter: jest.fn(),
25
- leave: jest.fn(),
26
- },
27
- Contact: {
28
- enter: jest.fn(),
29
- leave: jest.fn(),
30
- },
31
- License: {
32
- enter: jest.fn(),
33
- leave: jest.fn(),
34
- },
35
- };
36
-
37
- const testRuleSet: Oas3RuleSet = {
38
- test: jest.fn(() => {
39
- return visitors;
40
- }),
41
- };
42
-
43
- const document = parseYamlToDocument(
44
- outdent`
45
- openapi: 3.0.0
46
- info:
47
- contact: {}
48
- license: {}
49
- `,
50
- ''
51
- );
52
-
53
- await lintDocument({
54
- externalRefResolver: new BaseResolver(),
55
- document,
56
- config: makeConfigForRuleset(testRuleSet),
57
- });
58
-
59
- expect(testRuleSet.test).toBeCalledTimes(1);
60
- for (const fns of Object.values(visitors)) {
61
- expect(fns.enter).toBeCalled();
62
- expect(fns.leave).toBeCalled();
63
- }
64
- });
65
-
66
- it('should run legacy visitors', async () => {
67
- const visitors = {
68
- DefinitionRoot: {
69
- enter: jest.fn(),
70
- leave: jest.fn(),
71
- },
72
- PathMap: {
73
- enter: jest.fn(),
74
- leave: jest.fn(),
75
- },
76
- ServerVariableMap: {
77
- enter: jest.fn(),
78
- leave: jest.fn(),
79
- },
80
- MediaTypeMap: {
81
- enter: jest.fn(),
82
- leave: jest.fn(),
83
- },
84
- ExampleMap: {
85
- enter: jest.fn(),
86
- leave: jest.fn(),
87
- },
88
- HeaderMap: {
89
- enter: jest.fn(),
90
- leave: jest.fn(),
91
- },
92
- };
93
-
94
- const testRuleSet: Oas3RuleSet = {
95
- test: jest.fn(() => {
96
- return visitors;
97
- }),
98
- };
99
-
100
- const document = parseYamlToDocument(
101
- outdent`
102
- openapi: 3.0.0
103
- servers:
104
- - url: http://{test}.url
105
- variables:
106
- test: test
107
- paths:
108
- /test-path:
109
- get:
110
- responses:
111
- 200:
112
- headers: {}
113
- content:
114
- application/json:
115
- schema: {}
116
- examples: {}
117
- `,
118
- ''
119
- );
120
-
121
- await lintDocument({
122
- externalRefResolver: new BaseResolver(),
123
- document,
124
- config: makeConfigForRuleset(testRuleSet),
125
- });
126
-
127
- expect(testRuleSet.test).toBeCalledTimes(1);
128
- for (const fns of Object.values(visitors)) {
129
- expect(fns.enter).toBeCalled();
130
- expect(fns.leave).toBeCalled();
131
- }
132
- });
133
-
134
- it('should run nested visitors correctly', async () => {
135
- const calls: string[] = [];
136
-
137
- const testRuleSet: Oas3RuleSet = {
138
- test: jest.fn(() => {
139
- return {
140
- Operation: {
141
- enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
142
- leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
143
- Parameter: {
144
- enter: jest.fn((param, _ctx, parents) =>
145
- calls.push(`enter operation ${parents.Operation.operationId} > param ${param.name}`)
146
- ),
147
- leave: jest.fn((param, _ctx, parents) =>
148
- calls.push(`leave operation ${parents.Operation.operationId} > param ${param.name}`)
149
- ),
150
- },
151
- },
152
- Parameter: {
153
- enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
154
- leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
155
- },
156
- };
157
- }),
158
- };
159
-
160
- const document = parseYamlToDocument(
161
- outdent`
162
- openapi: 3.0.0
163
- info:
164
- contact: {}
165
- license: {}
166
- paths:
167
- /pet:
168
- parameters:
169
- - name: path-param
170
- get:
171
- operationId: get
172
- parameters:
173
- - name: get_a
174
- - name: get_b
175
- post:
176
- operationId: post
177
- parameters:
178
- - name: post_a
179
-
180
- `,
181
- ''
182
- );
183
-
184
- await lintDocument({
185
- externalRefResolver: new BaseResolver(),
186
- document,
187
- config: makeConfigForRuleset(testRuleSet),
188
- });
189
-
190
- expect(calls).toMatchInlineSnapshot(`
191
- Array [
192
- "enter param path-param",
193
- "leave param path-param",
194
- "enter operation: get",
195
- "enter operation get > param get_a",
196
- "enter param get_a",
197
- "leave param get_a",
198
- "leave operation get > param get_a",
199
- "enter operation get > param get_b",
200
- "enter param get_b",
201
- "leave param get_b",
202
- "leave operation get > param get_b",
203
- "leave operation: get",
204
- "enter operation: post",
205
- "enter operation post > param post_a",
206
- "enter param post_a",
207
- "leave param post_a",
208
- "leave operation post > param post_a",
209
- "leave operation: post",
210
- ]
211
- `);
212
- });
213
-
214
- it('should run nested visitors correctly oas2', async () => {
215
- const calls: string[] = [];
216
-
217
- const testRuleSet: Oas3RuleSet = {
218
- test: jest.fn(() => {
219
- return {
220
- Operation: {
221
- enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
222
- leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
223
- Parameter: {
224
- enter: jest.fn((param, _ctx, parents) =>
225
- calls.push(`enter operation ${parents.Operation.operationId} > param ${param.name}`)
226
- ),
227
- leave: jest.fn((param, _ctx, parents) =>
228
- calls.push(`leave operation ${parents.Operation.operationId} > param ${param.name}`)
229
- ),
230
- },
231
- },
232
- Parameter: {
233
- enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
234
- leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
235
- },
236
- };
237
- }),
238
- };
239
-
240
- const document = parseYamlToDocument(
241
- outdent`
242
- swagger: "2.0"
243
- info:
244
- contact: {}
245
- license: {}
246
- paths:
247
- /pet:
248
- parameters:
249
- - name: path-param
250
- get:
251
- operationId: get
252
- parameters:
253
- - name: get_a
254
- - name: get_b
255
- post:
256
- operationId: post
257
- parameters:
258
- - name: post_a
259
-
260
- `,
261
- ''
262
- );
263
-
264
- await lintDocument({
265
- externalRefResolver: new BaseResolver(),
266
- document,
267
- config: makeConfigForRuleset(testRuleSet, undefined, 'oas2'),
268
- });
269
-
270
- expect(calls).toMatchInlineSnapshot(`
271
- Array [
272
- "enter param path-param",
273
- "leave param path-param",
274
- "enter operation: get",
275
- "enter operation get > param get_a",
276
- "enter param get_a",
277
- "leave param get_a",
278
- "leave operation get > param get_a",
279
- "enter operation get > param get_b",
280
- "enter param get_b",
281
- "leave param get_b",
282
- "leave operation get > param get_b",
283
- "leave operation: get",
284
- "enter operation: post",
285
- "enter operation post > param post_a",
286
- "enter param post_a",
287
- "leave param post_a",
288
- "leave operation post > param post_a",
289
- "leave operation: post",
290
- ]
291
- `);
292
- });
293
-
294
- it('should resolve refs', async () => {
295
- const calls: string[] = [];
296
-
297
- const testRuleSet: Oas3RuleSet = {
298
- test: jest.fn(() => {
299
- return {
300
- Operation: {
301
- enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
302
- leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
303
- Parameter: {
304
- enter: jest.fn((param, _ctx, parents) =>
305
- calls.push(`enter operation ${parents.Operation.operationId} > param ${param.name}`)
306
- ),
307
- leave: jest.fn((param, _ctx, parents) =>
308
- calls.push(`leave operation ${parents.Operation.operationId} > param ${param.name}`)
309
- ),
310
- },
311
- },
312
- Parameter: {
313
- enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
314
- leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
315
- },
316
- };
317
- }),
318
- };
319
-
320
- const document = parseYamlToDocument(
321
- outdent`
322
- openapi: 3.0.0
323
- info:
324
- contact: {}
325
- license: {}
326
- paths:
327
- /pet:
328
- get:
329
- operationId: get
330
- parameters:
331
- - $ref: '#/components/parameters/shared_a'
332
- - name: get_b
333
- post:
334
- operationId: post
335
- parameters:
336
- - $ref: '#/components/parameters/shared_a'
337
- components:
338
- parameters:
339
- shared_a:
340
- name: shared-a
341
- `,
342
- ''
343
- );
344
-
345
- await lintDocument({
346
- externalRefResolver: new BaseResolver(),
347
- document,
348
- config: makeConfigForRuleset(testRuleSet),
349
- });
350
-
351
- expect(calls).toMatchInlineSnapshot(`
352
- Array [
353
- "enter operation: get",
354
- "enter operation get > param shared-a",
355
- "enter param shared-a",
356
- "leave param shared-a",
357
- "leave operation get > param shared-a",
358
- "enter operation get > param get_b",
359
- "enter param get_b",
360
- "leave param get_b",
361
- "leave operation get > param get_b",
362
- "leave operation: get",
363
- "enter operation: post",
364
- "enter operation post > param shared-a",
365
- "leave operation post > param shared-a",
366
- "leave operation: post",
367
- ]
368
- `);
369
- });
370
-
371
- it('should visit with context same refs with gaps in visitor simple', async () => {
372
- const calls: string[] = [];
373
-
374
- const testRuleSet: Oas3RuleSet = {
375
- test: jest.fn(() => {
376
- return {
377
- PathItem: {
378
- Parameter: {
379
- enter: jest.fn((param, _ctx, parents) =>
380
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`)
381
- ),
382
- },
383
- },
384
- };
385
- }),
386
- };
387
-
388
- const document = parseYamlToDocument(
389
- outdent`
390
- openapi: 3.0.0
391
- paths:
392
- /pet:
393
- id: pet
394
- parameters:
395
- $ref: '#/components/fake_parameters_list'
396
- get:
397
- operationId: get
398
- parameters:
399
- - $ref: '#/components/parameters/shared_a'
400
- - name: get_b
401
- /dog:
402
- id: dog
403
- post:
404
- operationId: post
405
- parameters:
406
- - $ref: '#/components/parameters/shared_a'
407
- components:
408
- fake_parameters_list:
409
- - name: path-param
410
- parameters:
411
- shared_a:
412
- name: shared-a
413
- `,
414
- ''
415
- );
416
-
417
- await lintDocument({
418
- externalRefResolver: new BaseResolver(),
419
- document,
420
- config: makeConfigForRuleset(testRuleSet),
421
- });
422
-
423
- expect(calls).toMatchInlineSnapshot(`
424
- Array [
425
- "enter path pet > param path-param",
426
- "enter path pet > param shared-a",
427
- "enter path pet > param get_b",
428
- "enter path dog > param shared-a",
429
- ]
430
- `);
431
- });
432
-
433
- it('should correctly visit more specific visitor', async () => {
434
- const calls: string[] = [];
435
-
436
- const testRuleSet: Oas3RuleSet = {
437
- test: jest.fn(() => {
438
- return {
439
- PathItem: {
440
- Parameter: {
441
- enter: jest.fn((param, _ctx, parents) =>
442
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`)
443
- ),
444
- },
445
- Operation: {
446
- Parameter: {
447
- enter: jest.fn((param, _ctx, parents) =>
448
- calls.push(
449
- `enter operation ${parents.Operation.operationId} > param ${param.name}`
450
- )
451
- ),
452
- },
453
- },
454
- },
455
- };
456
- }),
457
- };
458
-
459
- const document = parseYamlToDocument(
460
- outdent`
461
- openapi: 3.0.0
462
- paths:
463
- /pet:
464
- id: pet
465
- parameters:
466
- - name: path-param
467
- get:
468
- operationId: get
469
- parameters:
470
- - $ref: '#/components/parameters/shared_a'
471
- - name: get_b
472
- - name: get_c
473
- /dog:
474
- id: dog
475
- post:
476
- operationId: post
477
- parameters:
478
- - $ref: '#/components/parameters/shared_b'
479
- components:
480
- parameters:
481
- shared_a:
482
- name: shared-a
483
- shared_b:
484
- name: shared-b
485
- `,
486
- ''
487
- );
488
-
489
- await lintDocument({
490
- externalRefResolver: new BaseResolver(),
491
- document,
492
- config: makeConfigForRuleset(testRuleSet),
493
- });
494
-
495
- expect(calls).toMatchInlineSnapshot(`
496
- Array [
497
- "enter path pet > param path-param",
498
- "enter operation get > param shared-a",
499
- "enter operation get > param get_b",
500
- "enter operation get > param get_c",
501
- "enter operation post > param shared-b",
502
- ]
503
- `);
504
- });
505
-
506
- it('should visit with context same refs with gaps in visitor and nested rule', async () => {
507
- const calls: string[] = [];
508
-
509
- const testRuleSet: Oas3RuleSet = {
510
- test: jest.fn(() => {
511
- return {
512
- PathItem: {
513
- Parameter: {
514
- enter: jest.fn((param, _ctx, parents) =>
515
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`)
516
- ),
517
- leave: jest.fn((param, _ctx, parents) =>
518
- calls.push(`leave path ${parents.PathItem.id} > param ${param.name}`)
519
- ),
520
- },
521
- Operation(op, _ctx, parents) {
522
- calls.push(`enter path ${parents.PathItem.id} > op ${op.operationId}`);
523
- },
524
- },
525
- };
526
- }),
527
- };
528
-
529
- const document = parseYamlToDocument(
530
- outdent`
531
- openapi: 3.0.0
532
- paths:
533
- /pet:
534
- id: pet
535
- parameters:
536
- - name: path-param
537
- get:
538
- operationId: get
539
- parameters:
540
- - $ref: '#/components/parameters/shared_a'
541
- - name: get_b
542
- /dog:
543
- id: dog
544
- post:
545
- operationId: post
546
- parameters:
547
- - $ref: '#/components/parameters/shared_a'
548
- components:
549
- parameters:
550
- shared_a:
551
- name: shared-a
552
- `,
553
- ''
554
- );
555
-
556
- await lintDocument({
557
- externalRefResolver: new BaseResolver(),
558
- document,
559
- config: makeConfigForRuleset(testRuleSet),
560
- });
561
-
562
- expect(calls).toMatchInlineSnapshot(`
563
- Array [
564
- "enter path pet > param path-param",
565
- "leave path pet > param path-param",
566
- "enter path pet > op get",
567
- "enter path pet > param shared-a",
568
- "leave path pet > param shared-a",
569
- "enter path pet > param get_b",
570
- "leave path pet > param get_b",
571
- "enter path dog > op post",
572
- "enter path dog > param shared-a",
573
- "leave path dog > param shared-a",
574
- ]
575
- `);
576
- });
577
-
578
- it('should visit and do not recurse for circular refs top-level', async () => {
579
- const calls: string[] = [];
580
-
581
- const testRuleSet: Oas3RuleSet = {
582
- test: jest.fn(() => {
583
- return {
584
- Schema: jest.fn((schema: any) => calls.push(`enter schema ${schema.id}`)),
585
- };
586
- }),
587
- };
588
-
589
- const document = parseYamlToDocument(
590
- outdent`
591
- openapi: 3.0.0
592
- paths:
593
- /pet:
594
- id: pet
595
- parameters:
596
- - name: path-param
597
- schema:
598
- $ref: "#/components/parameters/shared_a"
599
- components:
600
- parameters:
601
- shared_a:
602
- id: 'shared_a'
603
- allOf:
604
- - $ref: "#/components/parameters/shared_a"
605
- - id: 'nested'
606
- `,
607
- ''
608
- );
609
-
610
- await lintDocument({
611
- externalRefResolver: new BaseResolver(),
612
- document,
613
- config: makeConfigForRuleset(testRuleSet),
614
- });
615
-
616
- expect(calls).toMatchInlineSnapshot(`
617
- Array [
618
- "enter schema shared_a",
619
- "enter schema nested",
620
- ]
621
- `);
622
- });
623
-
624
- it('should visit and do not recurse for circular refs with context', async () => {
625
- const calls: string[] = [];
626
-
627
- const testRuleSet: Oas3RuleSet = {
628
- test: jest.fn(() => {
629
- return {
630
- Parameter: {
631
- Schema: jest.fn((schema: any, _ctx, parents) =>
632
- calls.push(`enter param ${parents.Parameter.name} > schema ${schema.id}`)
633
- ),
634
- },
635
- };
636
- }),
637
- };
638
-
639
- const document = parseYamlToDocument(
640
- outdent`
641
- openapi: 3.0.0
642
- paths:
643
- /pet:
644
- id: pet
645
- parameters:
646
- - name: a
647
- schema:
648
- $ref: "#/components/parameters/shared_a"
649
- - name: b
650
- schema:
651
- $ref: "#/components/parameters/shared_a"
652
- components:
653
- parameters:
654
- shared_a:
655
- id: 'shared_a'
656
- properties:
657
- a:
658
- id: a
659
- allOf:
660
- - $ref: "#/components/parameters/shared_a"
661
- - id: 'nested'
662
- `,
663
- ''
664
- );
665
-
666
- await lintDocument({
667
- externalRefResolver: new BaseResolver(),
668
- document,
669
- config: makeConfigForRuleset(testRuleSet),
670
- });
671
-
672
- expect(calls).toMatchInlineSnapshot(`
673
- Array [
674
- "enter param a > schema shared_a",
675
- "enter param b > schema shared_a",
676
- ]
677
- `);
678
- });
679
-
680
- it('should correctly skip top level', async () => {
681
- const calls: string[] = [];
682
-
683
- const testRuleSet: Oas3RuleSet = {
684
- test: jest.fn(() => {
685
- return {
686
- Operation: {
687
- skip: (op) => op.operationId === 'put',
688
- enter: jest.fn((op) => calls.push(`enter operation ${op.operationId}`)),
689
- leave: jest.fn((op) => calls.push(`leave operation ${op.operationId}`)),
690
- },
691
- };
692
- }),
693
- };
694
-
695
- const document = parseYamlToDocument(
696
- outdent`
697
- openapi: 3.0.0
698
- paths:
699
- /pet:
700
- get:
701
- operationId: get
702
- put:
703
- operationId: put
704
- `,
705
- ''
706
- );
707
-
708
- await lintDocument({
709
- externalRefResolver: new BaseResolver(),
710
- document,
711
- config: makeConfigForRuleset(testRuleSet),
712
- });
713
-
714
- expect(calls).toMatchInlineSnapshot(`
715
- Array [
716
- "enter operation get",
717
- "leave operation get",
718
- ]
719
- `);
720
- });
721
-
722
- it('should correctly skip nested levels', async () => {
723
- const calls: string[] = [];
724
-
725
- const testRuleSet: Oas3RuleSet = {
726
- test: jest.fn(() => {
727
- return {
728
- Operation: {
729
- skip: (op) => op.operationId === 'put',
730
- Parameter: jest.fn((param, _ctx, parents) =>
731
- calls.push(`enter operation ${parents.Operation.operationId} > param ${param.name}`)
732
- ),
733
- },
734
- };
735
- }),
736
- };
737
-
738
- const document = parseYamlToDocument(
739
- outdent`
740
- openapi: 3.0.0
741
- paths:
742
- /pet:
743
- get:
744
- operationId: get
745
- parameters:
746
- - $ref: '#/components/parameters/shared_a'
747
- - name: get_b
748
- - name: get_c
749
- put:
750
- operationId: put
751
- parameters:
752
- - $ref: '#/components/parameters/shared_a'
753
- - name: get_b
754
- - name: get_c
755
- components:
756
- parameters:
757
- shared_a:
758
- name: shared-a
759
- `,
760
- ''
761
- );
762
-
763
- await lintDocument({
764
- externalRefResolver: new BaseResolver(),
765
- document,
766
- config: makeConfigForRuleset(testRuleSet),
767
- });
768
-
769
- expect(calls).toMatchInlineSnapshot(`
770
- Array [
771
- "enter operation get > param shared-a",
772
- "enter operation get > param get_b",
773
- "enter operation get > param get_c",
774
- ]
775
- `);
776
- });
777
-
778
- it('should correctly visit more specific visitor with skips', async () => {
779
- const calls: string[] = [];
780
-
781
- const testRuleSet: Oas3RuleSet = {
782
- test: jest.fn(() => {
783
- return {
784
- PathItem: {
785
- Parameter: {
786
- enter: jest.fn((param, _ctx, parents) =>
787
- calls.push(`enter path ${parents.PathItem.id} > param ${param.name}`)
788
- ),
789
- leave: jest.fn((param, _ctx, parents) =>
790
- calls.push(`leave path ${parents.PathItem.id} > param ${param.name}`)
791
- ),
792
- },
793
- Operation: {
794
- skip: (op) => op.operationId === 'put',
795
- Parameter: {
796
- enter: jest.fn((param, _ctx, parents) =>
797
- calls.push(
798
- `enter operation ${parents.Operation.operationId} > param ${param.name}`
799
- )
800
- ),
801
- leave: jest.fn((param, _ctx, parents) =>
802
- calls.push(
803
- `leave operation ${parents.Operation.operationId} > param ${param.name}`
804
- )
805
- ),
806
- },
807
- },
808
- },
809
- };
810
- }),
811
- };
812
-
813
- const document = parseYamlToDocument(
814
- outdent`
815
- openapi: 3.0.0
816
- paths:
817
- /pet:
818
- id: pet
819
- parameters:
820
- - name: path-param
821
- get:
822
- operationId: get
823
- parameters:
824
- - $ref: '#/components/parameters/shared_a'
825
- - name: get_b
826
- - name: get_c
827
- put:
828
- operationId: put
829
- parameters:
830
- - $ref: '#/components/parameters/shared_a'
831
- - name: get_b
832
- - name: get_c
833
- /dog:
834
- id: dog
835
- post:
836
- operationId: post
837
- parameters:
838
- - $ref: '#/components/parameters/shared_b'
839
- components:
840
- parameters:
841
- shared_a:
842
- name: shared-a
843
- shared_b:
844
- name: shared-b
845
- `,
846
- ''
847
- );
848
-
849
- await lintDocument({
850
- externalRefResolver: new BaseResolver(),
851
- document,
852
- config: makeConfigForRuleset(testRuleSet),
853
- });
854
-
855
- expect(calls).toMatchInlineSnapshot(`
856
- Array [
857
- "enter path pet > param path-param",
858
- "leave path pet > param path-param",
859
- "enter operation get > param shared-a",
860
- "leave operation get > param shared-a",
861
- "enter operation get > param get_b",
862
- "leave operation get > param get_b",
863
- "enter operation get > param get_c",
864
- "leave operation get > param get_c",
865
- "enter operation post > param shared-b",
866
- "leave operation post > param shared-b",
867
- ]
868
- `);
869
- });
870
-
871
- it('should correctly visit with nested rules', async () => {
872
- const calls: string[] = [];
873
-
874
- const testRuleSet: Oas3RuleSet = {
875
- test: jest.fn(() => {
876
- return {
877
- Schema: {
878
- Schema: {
879
- enter: jest.fn((schema: any, _ctx, parents) =>
880
- calls.push(`enter nested schema ${parents.Schema.id} > ${schema.id}`)
881
- ),
882
- leave: jest.fn((schema: any, _ctx, parents) =>
883
- calls.push(`leave nested schema ${parents.Schema.id} > ${schema.id}`)
884
- ),
885
- },
886
- },
887
- };
888
- }),
889
- };
890
-
891
- const document = parseYamlToDocument(
892
- outdent`
893
- openapi: 3.0.0
894
- paths:
895
- /pet:
896
- get:
897
- requestBody:
898
- content:
899
- application/json:
900
- schema:
901
- id: inline-top
902
- type: object
903
- properties:
904
- b:
905
- $ref: "#/components/schemas/b"
906
- a:
907
- type: object
908
- id: inline-nested-2
909
- properties:
910
- a:
911
- id: inline-nested-nested-2
912
- components:
913
- schemas:
914
- b:
915
- id: inline-top
916
- type: object
917
- properties:
918
- a:
919
- type: object
920
- id: inline-nested
921
- properties:
922
- a:
923
- id: inline-nested-nested
924
- `,
925
- 'foobar.yaml'
926
- );
927
-
928
- await lintDocument({
929
- externalRefResolver: new BaseResolver(),
930
- document,
931
- config: makeConfigForRuleset(testRuleSet),
932
- });
933
-
934
- expect(calls).toMatchInlineSnapshot(`
935
- Array [
936
- "enter nested schema inline-top > inline-top",
937
- "enter nested schema inline-top > inline-nested",
938
- "enter nested schema inline-nested > inline-nested-nested",
939
- "leave nested schema inline-nested > inline-nested-nested",
940
- "leave nested schema inline-top > inline-nested",
941
- "leave nested schema inline-top > inline-top",
942
- "enter nested schema inline-top > inline-nested-2",
943
- "enter nested schema inline-nested-2 > inline-nested-nested-2",
944
- "leave nested schema inline-nested-2 > inline-nested-nested-2",
945
- "leave nested schema inline-top > inline-nested-2",
946
- ]
947
- `);
948
- });
949
-
950
- it('should correctly visit refs', async () => {
951
- const calls: string[] = [];
952
-
953
- const testRuleSet: Oas3RuleSet = {
954
- test: jest.fn(() => {
955
- return {
956
- ref(node, _, { node: target }) {
957
- calls.push(`enter $ref ${node.$ref} with target ${target?.name}`);
958
- },
959
- };
960
- }),
961
- };
962
-
963
- const document = parseYamlToDocument(
964
- outdent`
965
- openapi: 3.0.0
966
- paths:
967
- /pet:
968
- id: pet
969
- parameters:
970
- - name: path-param
971
- get:
972
- operationId: get
973
- parameters:
974
- - $ref: '#/components/parameters/shared_b'
975
- put:
976
- operationId: put
977
- parameters:
978
- - $ref: '#/components/parameters/shared_a'
979
- /dog:
980
- id: dog
981
- post:
982
- operationId: post
983
- schema:
984
- example:
985
- $ref: 123
986
- parameters:
987
- - $ref: '#/components/parameters/shared_a'
988
- components:
989
- parameters:
990
- shared_a:
991
- name: shared-a
992
- shared_b:
993
- name: shared-b
994
- schema:
995
- $ref: '#/components/parameters/shared_b'
996
- `,
997
- 'foobar.yaml'
998
- );
999
-
1000
- await lintDocument({
1001
- externalRefResolver: new BaseResolver(),
1002
- document,
1003
- config: makeConfigForRuleset(testRuleSet),
1004
- });
1005
-
1006
- expect(calls).toMatchInlineSnapshot(`
1007
- Array [
1008
- "enter $ref #/components/parameters/shared_b with target shared-b",
1009
- "enter $ref #/components/parameters/shared_b with target shared-b",
1010
- "enter $ref #/components/parameters/shared_a with target shared-a",
1011
- "enter $ref #/components/parameters/shared_a with target shared-a",
1012
- ]
1013
- `);
1014
- });
1015
-
1016
- it('should correctly visit refs', async () => {
1017
- const calls: string[] = [];
1018
-
1019
- const testRuleSet: Oas3RuleSet = {
1020
- test: jest.fn(() => {
1021
- return {
1022
- NamedSchemas: {
1023
- Schema(node, { key }) {
1024
- calls.push(`enter schema ${key}: ${node.type}`);
1025
- },
1026
- },
1027
- };
1028
- }),
1029
- };
1030
-
1031
- const document = parseYamlToDocument(
1032
- outdent`
1033
- openapi: 3.0.0
1034
- components:
1035
- schemas:
1036
- a:
1037
- type: string
1038
- b:
1039
- type: number
1040
- `,
1041
- 'foobar.yaml'
1042
- );
1043
-
1044
- await lintDocument({
1045
- externalRefResolver: new BaseResolver(),
1046
- document,
1047
- config: makeConfigForRuleset(testRuleSet),
1048
- });
1049
-
1050
- expect(calls).toMatchInlineSnapshot(`
1051
- Array [
1052
- "enter schema a: string",
1053
- "enter schema b: number",
1054
- ]
1055
- `);
1056
- });
1057
-
1058
- it('should correctly visit any visitor', async () => {
1059
- const calls: string[] = [];
1060
-
1061
- const testRuleSet: Oas3RuleSet = {
1062
- test: jest.fn(() => {
1063
- return {
1064
- ref: {
1065
- enter(ref: any) {
1066
- calls.push(`enter ref ${ref.$ref}`);
1067
- },
1068
- leave(ref) {
1069
- calls.push(`leave ref ${ref.$ref}`);
1070
- },
1071
- },
1072
- any: {
1073
- enter(_node: any, { type }) {
1074
- calls.push(`enter ${type.name}`);
1075
- },
1076
- leave(_node, { type }) {
1077
- calls.push(`leave ${type.name}`);
1078
- },
1079
- },
1080
- };
1081
- }),
1082
- };
1083
-
1084
- const document = parseYamlToDocument(
1085
- outdent`
1086
- openapi: 3.0.0
1087
- paths:
1088
- /pet:
1089
- id: pet
1090
- parameters:
1091
- - name: path-param
1092
- get:
1093
- operationId: get
1094
- parameters:
1095
- - $ref: '#/components/parameters/shared_a'
1096
- - name: get_b
1097
- - name: get_c
1098
- components:
1099
- parameters:
1100
- shared_a:
1101
- name: shared-a
1102
- schemas:
1103
- a:
1104
- type: object
1105
- `,
1106
- ''
1107
- );
1108
-
1109
- await lintDocument({
1110
- externalRefResolver: new BaseResolver(),
1111
- document,
1112
- config: makeConfigForRuleset(testRuleSet),
1113
- });
1114
-
1115
- expect(calls).toMatchInlineSnapshot(`
1116
- Array [
1117
- "enter Root",
1118
- "enter Paths",
1119
- "enter PathItem",
1120
- "enter ParameterList",
1121
- "enter Parameter",
1122
- "leave Parameter",
1123
- "leave ParameterList",
1124
- "enter Operation",
1125
- "enter ParameterList",
1126
- "enter ref #/components/parameters/shared_a",
1127
- "enter Parameter",
1128
- "leave Parameter",
1129
- "leave ref #/components/parameters/shared_a",
1130
- "enter Parameter",
1131
- "leave Parameter",
1132
- "enter Parameter",
1133
- "leave Parameter",
1134
- "leave ParameterList",
1135
- "leave Operation",
1136
- "leave PathItem",
1137
- "leave Paths",
1138
- "enter Components",
1139
- "enter NamedParameters",
1140
- "leave NamedParameters",
1141
- "enter NamedSchemas",
1142
- "enter Schema",
1143
- "leave Schema",
1144
- "leave NamedSchemas",
1145
- "leave Components",
1146
- "leave Root",
1147
- ]
1148
- `);
1149
- });
1150
- });
1151
-
1152
- describe('context.report', () => {
1153
- it('should report errors correctly', async () => {
1154
- const testRuleSet: Oas3RuleSet = {
1155
- test: jest.fn(() => {
1156
- return {
1157
- Parameter: {
1158
- enter: jest.fn((param, ctx) => {
1159
- if (param.name.indexOf('_') > -1) {
1160
- ctx.report({
1161
- message: `Parameter name shouldn't contain '_: ${param.name}`,
1162
- });
1163
- }
1164
- }),
1165
- },
1166
- };
1167
- }),
1168
- };
1169
-
1170
- const document = parseYamlToDocument(
1171
- outdent`
1172
- openapi: 3.0.0
1173
- info:
1174
- contact: {}
1175
- license: {}
1176
- paths:
1177
- /pet:
1178
- parameters:
1179
- - name: path-param
1180
- get:
1181
- operationId: get
1182
- parameters:
1183
- - name: get_a
1184
- - name: get_b
1185
- post:
1186
- operationId: post
1187
- parameters:
1188
- - $ref: '#/components/parameters/shared_a'
1189
- components:
1190
- parameters:
1191
- shared_a:
1192
- name: shared_a
1193
- `,
1194
- 'foobar.yaml'
1195
- );
1196
-
1197
- const results = await lintDocument({
1198
- externalRefResolver: new BaseResolver(),
1199
- document,
1200
- config: makeConfigForRuleset(testRuleSet),
1201
- });
1202
-
1203
- expect(results).toHaveLength(3);
1204
- expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
1205
- Array [
1206
- Object {
1207
- "location": Array [
1208
- Object {
1209
- "pointer": "#/paths/~1pet/get/parameters/0",
1210
- "reportOnKey": false,
1211
- "source": "foobar.yaml",
1212
- },
1213
- ],
1214
- "message": "Parameter name shouldn't contain '_: get_a",
1215
- "ruleId": "test/test",
1216
- "severity": "error",
1217
- "suggest": Array [],
1218
- },
1219
- Object {
1220
- "location": Array [
1221
- Object {
1222
- "pointer": "#/paths/~1pet/get/parameters/1",
1223
- "reportOnKey": false,
1224
- "source": "foobar.yaml",
1225
- },
1226
- ],
1227
- "message": "Parameter name shouldn't contain '_: get_b",
1228
- "ruleId": "test/test",
1229
- "severity": "error",
1230
- "suggest": Array [],
1231
- },
1232
- Object {
1233
- "location": Array [
1234
- Object {
1235
- "pointer": "#/components/parameters/shared_a",
1236
- "reportOnKey": false,
1237
- "source": "foobar.yaml",
1238
- },
1239
- ],
1240
- "message": "Parameter name shouldn't contain '_: shared_a",
1241
- "ruleId": "test/test",
1242
- "severity": "error",
1243
- "suggest": Array [],
1244
- },
1245
- ]
1246
- `);
1247
- });
1248
-
1249
- it('should report errors correctly', async () => {
1250
- const testRuleSet: Oas3RuleSet = {
1251
- test: jest.fn(() => {
1252
- return {
1253
- Parameter: {
1254
- enter: jest.fn((param, ctx) => {
1255
- if (param.name.indexOf('_') > -1) {
1256
- ctx.report({
1257
- message: `Parameter name shouldn't contain '_: ${param.name}`,
1258
- });
1259
- }
1260
- }),
1261
- },
1262
- };
1263
- }),
1264
- };
1265
-
1266
- const cwd = path.join(__dirname, 'fixtures/refs');
1267
- const externalRefResolver = new BaseResolver();
1268
- const document = (await externalRefResolver.resolveDocument(
1269
- null,
1270
- `${cwd}/openapi-with-external-refs.yaml`
1271
- )) as Document;
1272
-
1273
- if (document === null) {
1274
- throw 'Should never happen';
1275
- }
1276
-
1277
- const results = await lintDocument({
1278
- externalRefResolver: new BaseResolver(),
1279
- document,
1280
- config: makeConfigForRuleset(testRuleSet),
1281
- });
1282
-
1283
- expect(results).toHaveLength(4);
1284
- expect(replaceSourceWithRef(results, cwd)).toMatchInlineSnapshot(`
1285
- Array [
1286
- Object {
1287
- "location": Array [
1288
- Object {
1289
- "pointer": "#/components/parameters/path-param",
1290
- "reportOnKey": false,
1291
- "source": "openapi-with-external-refs.yaml",
1292
- },
1293
- ],
1294
- "message": "Parameter name shouldn't contain '_: path_param",
1295
- "ruleId": "test/test",
1296
- "severity": "error",
1297
- "suggest": Array [],
1298
- },
1299
- Object {
1300
- "location": Array [
1301
- Object {
1302
- "pointer": "#/components/parameters/param-a",
1303
- "reportOnKey": false,
1304
- "source": "openapi-with-external-refs.yaml",
1305
- },
1306
- ],
1307
- "message": "Parameter name shouldn't contain '_: param_a",
1308
- "ruleId": "test/test",
1309
- "severity": "error",
1310
- "suggest": Array [],
1311
- },
1312
- Object {
1313
- "location": Array [
1314
- Object {
1315
- "pointer": "#/",
1316
- "reportOnKey": false,
1317
- "source": "param-c.yaml",
1318
- },
1319
- ],
1320
- "message": "Parameter name shouldn't contain '_: param_c",
1321
- "ruleId": "test/test",
1322
- "severity": "error",
1323
- "suggest": Array [],
1324
- },
1325
- Object {
1326
- "location": Array [
1327
- Object {
1328
- "pointer": "#/",
1329
- "reportOnKey": false,
1330
- "source": "param-b.yaml",
1331
- },
1332
- ],
1333
- "message": "Parameter name shouldn't contain '_: param_b",
1334
- "ruleId": "test/test",
1335
- "severity": "error",
1336
- "suggest": Array [],
1337
- },
1338
- ]
1339
- `);
1340
- });
1341
- });
1342
-
1343
- describe('context.resolve', () => {
1344
- it('should resolve refs correctly', async () => {
1345
- const testRuleSet: Oas3RuleSet = {
1346
- test: jest.fn(() => {
1347
- return {
1348
- Schema: jest.fn((schema, { resolve }) => {
1349
- if (schema.properties) {
1350
- expect(schema.properties.a.$ref).toBeDefined();
1351
- const { location, node } = resolve(schema.properties.a);
1352
- expect(node).toMatchInlineSnapshot(`
1353
- Object {
1354
- "type": "string",
1355
- }
1356
- `);
1357
- expect(location?.pointer).toEqual('#/components/schemas/b');
1358
- expect(location?.source).toStrictEqual(document.source);
1359
- }
1360
- }),
1361
- };
1362
- }),
1363
- };
1364
-
1365
- const document = parseYamlToDocument(
1366
- outdent`
1367
- openapi: 3.0.0
1368
- info:
1369
- contact: {}
1370
- license: {}
1371
- paths: {}
1372
- components:
1373
- schemas:
1374
- b:
1375
- type: string
1376
- a:
1377
- type: object
1378
- properties:
1379
- a:
1380
- $ref: '#/components/schemas/b'
1381
- `,
1382
- 'foobar.yaml'
1383
- );
1384
-
1385
- await lintDocument({
1386
- externalRefResolver: new BaseResolver(),
1387
- document,
1388
- config: makeConfigForRuleset(testRuleSet),
1389
- });
1390
- });
1391
- });
1392
-
1393
- describe('type extensions', () => {
1394
- each([
1395
- ['3.0.0', 'oas3_0'],
1396
- ['3.1.0', 'oas3_1'],
1397
- ]).it('should correctly visit OpenAPI %s extended types', async (openapi, oas) => {
1398
- const calls: string[] = [];
1399
-
1400
- const testRuleSet: Oas3RuleSet = {
1401
- test: jest.fn(() => {
1402
- return {
1403
- any: {
1404
- enter(_node: any, { type }) {
1405
- calls.push(`enter ${type.name}`);
1406
- },
1407
- leave(_node, { type }) {
1408
- calls.push(`leave ${type.name}`);
1409
- },
1410
- },
1411
- XWebHooks: {
1412
- enter(hook: any) {
1413
- calls.push(`enter hook ${hook.name}`);
1414
- },
1415
- leave(hook) {
1416
- calls.push(`leave hook ${hook.name}`);
1417
- },
1418
- },
1419
- };
1420
- }),
1421
- };
1422
-
1423
- const document = parseYamlToDocument(
1424
- outdent`
1425
- openapi: ${openapi}
1426
- x-webhooks:
1427
- name: test
1428
- parameters:
1429
- - name: a
1430
- `,
1431
- 'foobar.yaml'
1432
- );
1433
-
1434
- await lintDocument({
1435
- externalRefResolver: new BaseResolver(),
1436
- document,
1437
- config: makeConfigForRuleset(testRuleSet, {
1438
- typeExtension: {
1439
- oas3(types, version) {
1440
- expect(version).toEqual(oas);
1441
-
1442
- return {
1443
- ...types,
1444
- XWebHooks: {
1445
- properties: {
1446
- parameters: listOf('Parameter'),
1447
- },
1448
- },
1449
- Root: {
1450
- ...types.Root,
1451
- properties: {
1452
- ...types.Root.properties,
1453
- 'x-webhooks': 'XWebHooks',
1454
- },
1455
- },
1456
- };
1457
- },
1458
- },
1459
- }),
1460
- });
1461
-
1462
- expect(calls).toMatchInlineSnapshot(`
1463
- Array [
1464
- "enter Root",
1465
- "enter XWebHooks",
1466
- "enter hook test",
1467
- "enter ParameterList",
1468
- "enter Parameter",
1469
- "leave Parameter",
1470
- "leave ParameterList",
1471
- "leave hook test",
1472
- "leave XWebHooks",
1473
- "leave Root",
1474
- ]
1475
- `);
1476
- });
1477
- });
1478
-
1479
- describe('ignoreNextRules', () => {
1480
- it('should correctly skip top level', async () => {
1481
- const calls: string[] = [];
1482
-
1483
- const testRuleSet: Oas3RuleSet = {
1484
- skip: jest.fn(() => {
1485
- return {
1486
- Operation: {
1487
- enter: jest.fn((op, ctx) => {
1488
- if (op.operationId === 'get') {
1489
- ctx.ignoreNextVisitorsOnNode();
1490
- calls.push(`enter and skip operation ${op.operationId}`);
1491
- } else {
1492
- calls.push(`enter and not skip operation ${op.operationId}`);
1493
- }
1494
- }),
1495
- leave: jest.fn((op) => {
1496
- if (op.operationId === 'get') {
1497
- calls.push(`leave skipped operation ${op.operationId}`);
1498
- } else {
1499
- calls.push(`leave not skipped operation ${op.operationId}`);
1500
- }
1501
- }),
1502
- },
1503
- };
1504
- }),
1505
- test: jest.fn(() => {
1506
- return {
1507
- Operation: {
1508
- enter: jest.fn((op) => calls.push(`enter operation ${op.operationId}`)),
1509
- leave: jest.fn((op) => calls.push(`leave operation ${op.operationId}`)),
1510
- },
1511
- };
1512
- }),
1513
- };
1514
-
1515
- const document = parseYamlToDocument(
1516
- outdent`
1517
- openapi: 3.0.0
1518
- paths:
1519
- /pet:
1520
- get:
1521
- operationId: get
1522
- put:
1523
- operationId: put
1524
- `,
1525
- ''
1526
- );
1527
-
1528
- await lintDocument({
1529
- externalRefResolver: new BaseResolver(),
1530
- document,
1531
- config: makeConfigForRuleset(testRuleSet),
1532
- });
1533
-
1534
- expect(calls).toMatchInlineSnapshot(`
1535
- Array [
1536
- "enter and skip operation get",
1537
- "leave skipped operation get",
1538
- "enter and not skip operation put",
1539
- "enter operation put",
1540
- "leave not skipped operation put",
1541
- "leave operation put",
1542
- ]
1543
- `);
1544
- });
1545
- });