@redocly/openapi-docs 3.24.0-next.9 → 3.24.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.
Files changed (314) hide show
  1. package/dist/{redocly-openapi-docs.min.AiChatProvider-DcsGB2gP.js → redocly-openapi-docs.min.AiChatProvider-j-VDfFJ9.js} +3 -3
  2. package/dist/{redocly-openapi-docs.min.AiChatSqliteDBStorage-wCZA4usG.js → redocly-openapi-docs.min.AiChatSqliteDBStorage-BBRBmffc.js} +1 -1
  3. package/dist/{redocly-openapi-docs.min.AiPanel-jo7fqtSt.js → redocly-openapi-docs.min.AiPanel-DTzHqAiI.js} +116 -116
  4. package/dist/redocly-openapi-docs.min.FileWatcher-DDoyaS7A.js +1 -0
  5. package/dist/redocly-openapi-docs.min.Observable-D6wKbFwB.js +1 -0
  6. package/dist/redocly-openapi-docs.min.SemanticSearchService-DNFOPBZK.js +1 -0
  7. package/dist/{redocly-openapi-docs.min.SqliteDBStorage-B_f6WR8o.js → redocly-openapi-docs.min.SqliteDBStorage-Dy40Vq04.js} +1 -1
  8. package/dist/redocly-openapi-docs.min.TauriFileSystemAdapter-CpViFqJQ.js +1 -0
  9. package/dist/redocly-openapi-docs.min.TauriRootStorage-TCUrp2uB.js +1 -0
  10. package/dist/redocly-openapi-docs.min.ai-chat-mappers-CmX-8902.js +1 -0
  11. package/dist/redocly-openapi-docs.min.core-BYyFOtMX.js +1 -0
  12. package/dist/redocly-openapi-docs.min.external-resolver-BkceRyB4.js +2 -0
  13. package/dist/redocly-openapi-docs.min.index-BCcol5vU.js +1 -0
  14. package/dist/redocly-openapi-docs.min.index-C6uU_v-b.js +1 -0
  15. package/dist/redocly-openapi-docs.min.index-CmXZfuiZ.js +7730 -0
  16. package/dist/redocly-openapi-docs.min.index-DVWw0ICA.js +1 -0
  17. package/dist/redocly-openapi-docs.min.index-YnvLQkG_.js +1 -0
  18. package/dist/redocly-openapi-docs.min.index-xl_tBaHD.js +1 -0
  19. package/dist/redocly-openapi-docs.min.js +1 -1
  20. package/dist/{redocly-openapi-docs.min.lint-C-zlwxhp.js → redocly-openapi-docs.min.lint-2YpbCz3r.js} +69 -69
  21. package/dist/{redocly-openapi-docs.min.lint-graphql-qEh9cZHx.js → redocly-openapi-docs.min.lint-graphql-Bgfcu2tP.js} +1 -1
  22. package/dist/redocly-openapi-docs.min.periodic-revalidation-Dsp-n7ui.js +1 -0
  23. package/dist/redocly-openapi-docs.min.promise-map-limit-Db_42GvV.js +1 -0
  24. package/dist/{redocly-openapi-docs.min.respect-run-hfNPYQ9x.js → redocly-openapi-docs.min.respect-run-Ct8taisL.js} +1 -1
  25. package/dist/redocly-openapi-docs.min.standalone-BPCdJgtH.js +11995 -0
  26. package/dist/redocly-openapi-docs.min.tauri-path-CmqBCxGb.js +1 -0
  27. package/dist/{redocly-openapi-docs.min.useAiChatQueries-DgSsCKMW.js → redocly-openapi-docs.min.useAiChatQueries-t8oy8jik.js} +80 -80
  28. package/lib/components/ApiInfo/__tests__/ApiInfo.test.d.ts +1 -0
  29. package/lib/components/ApiInfo/__tests__/ApiInfo.test.js +46 -0
  30. package/lib/components/Callbacks/CallbackOperation.js +1 -1
  31. package/lib/components/Callbacks/__tests__/Callbacks.test.d.ts +1 -0
  32. package/lib/components/Callbacks/__tests__/Callbacks.test.js +46 -0
  33. package/lib/components/Content/__tests__/useAutoScroll.test.d.ts +1 -0
  34. package/lib/components/Content/__tests__/useAutoScroll.test.js +88 -0
  35. package/lib/components/Content/useAutoScroll.js +1 -1
  36. package/lib/components/ContentItem/__tests__/useIsExpanded.test.d.ts +1 -0
  37. package/lib/components/ContentItem/__tests__/useIsExpanded.test.js +123 -0
  38. package/lib/components/ContentItem/useIsExpanded.js +1 -1
  39. package/lib/components/ContentItems/ContentItems.js +1 -1
  40. package/lib/components/ContentItems/VirtualList.js +1 -1
  41. package/lib/components/ContentItems/__tests__/Items.test.d.ts +1 -0
  42. package/lib/components/ContentItems/__tests__/Items.test.js +66 -0
  43. package/lib/components/ContentItems/__tests__/VirtualList.test.d.ts +1 -0
  44. package/lib/components/ContentItems/__tests__/VirtualList.test.js +135 -0
  45. package/lib/components/ContentItems/useScrollOnRender.js +1 -1
  46. package/lib/components/Discriminator/__tests__/DiscriminatorDropdown.test.d.ts +1 -0
  47. package/lib/components/Discriminator/__tests__/DiscriminatorDropdown.test.js +63 -0
  48. package/lib/components/Download/__tests__/DownloadSpecification.test.d.ts +1 -0
  49. package/lib/components/Download/__tests__/DownloadSpecification.test.js +52 -0
  50. package/lib/components/ExpandAllButton/__tests__/ExpandAllButton.test.d.ts +1 -0
  51. package/lib/components/ExpandAllButton/__tests__/ExpandAllButton.test.js +60 -0
  52. package/lib/components/ExpandAllButton/__tests__/helpers.test.d.ts +1 -0
  53. package/lib/components/ExpandAllButton/__tests__/helpers.test.js +133 -0
  54. package/lib/components/Language/__tests__/LanguageDropdown.test.d.ts +1 -0
  55. package/lib/components/Language/__tests__/LanguageDropdown.test.js +23 -0
  56. package/lib/components/Markdown/__tests__/Markdown.test.d.ts +1 -0
  57. package/lib/components/Markdown/__tests__/Markdown.test.js +34 -0
  58. package/lib/components/McpOverview/__tests__/McpOverview.test.d.ts +1 -0
  59. package/lib/components/McpOverview/__tests__/McpOverview.test.js +66 -0
  60. package/lib/components/McpTool/__tests__/McpPrompt.test.d.ts +1 -0
  61. package/lib/components/McpTool/__tests__/McpPrompt.test.js +57 -0
  62. package/lib/components/McpTool/__tests__/McpResource.test.d.ts +1 -0
  63. package/lib/components/McpTool/__tests__/McpResource.test.js +81 -0
  64. package/lib/components/McpTool/__tests__/McpTool.test.d.ts +1 -0
  65. package/lib/components/McpTool/__tests__/McpTool.test.js +82 -0
  66. package/lib/components/MediaTypeSwitch/__tests__/MediaTypesSwitch.test.d.ts +1 -0
  67. package/lib/components/MediaTypeSwitch/__tests__/MediaTypesSwitch.test.js +79 -0
  68. package/lib/components/OperationItem/__tests__/OperationItem.test.d.ts +1 -0
  69. package/lib/components/OperationItem/__tests__/OperationItem.test.js +70 -0
  70. package/lib/components/OperationItem/__tests__/__mocks__/mock-intersection-observer.d.ts +16 -0
  71. package/lib/components/OperationItem/__tests__/__mocks__/mock-intersection-observer.js +42 -0
  72. package/lib/components/Overview/__tests__/Overview.test.d.ts +1 -0
  73. package/lib/components/Overview/__tests__/Overview.test.js +59 -0
  74. package/lib/components/PayloadSamples/__tests__/Example.test.d.ts +1 -0
  75. package/lib/components/PayloadSamples/__tests__/Example.test.js +36 -0
  76. package/lib/components/PayloadSamples/__tests__/ExampleValue.test.d.ts +1 -0
  77. package/lib/components/PayloadSamples/__tests__/ExampleValue.test.js +197 -0
  78. package/lib/components/PayloadSamples/__tests__/PayloadSamples.test.d.ts +1 -0
  79. package/lib/components/PayloadSamples/__tests__/PayloadSamples.test.js +38 -0
  80. package/lib/components/PropertyDetails/__tests__/Extensions.test.d.ts +1 -0
  81. package/lib/components/PropertyDetails/__tests__/Extensions.test.js +21 -0
  82. package/lib/components/PropertyDetails/__tests__/FieldDetail.test.d.ts +1 -0
  83. package/lib/components/PropertyDetails/__tests__/FieldDetail.test.js +52 -0
  84. package/lib/components/PropertyDetails/__tests__/FieldDetails.test.d.ts +1 -0
  85. package/lib/components/PropertyDetails/__tests__/FieldDetails.test.js +191 -0
  86. package/lib/components/PropertyDetails/__tests__/PropertyDetails.test.d.ts +1 -0
  87. package/lib/components/PropertyDetails/__tests__/PropertyDetails.test.js +365 -0
  88. package/lib/components/PropertyDetails/__tests__/cycleColorsByLevel.test.d.ts +1 -0
  89. package/lib/components/PropertyDetails/__tests__/cycleColorsByLevel.test.js +23 -0
  90. package/lib/components/RedoclyOpenAPIDocs/__tests__/AppProvider.test.d.ts +1 -0
  91. package/lib/components/RedoclyOpenAPIDocs/__tests__/AppProvider.test.js +16 -0
  92. package/lib/components/RedoclyOpenAPIDocs/__tests__/RedoclyOpenAPIDocs.test.d.ts +1 -0
  93. package/lib/components/RedoclyOpenAPIDocs/__tests__/RedoclyOpenAPIDocs.test.js +104 -0
  94. package/lib/components/RenderHook/__tests__/RenderHook.test.d.ts +1 -0
  95. package/lib/components/RenderHook/__tests__/RenderHook.test.js +15 -0
  96. package/lib/components/Replay/__tests__/utils.test.d.ts +1 -0
  97. package/lib/components/Replay/__tests__/utils.test.js +526 -0
  98. package/lib/components/Request/__tests__/RequestDetails.test.d.ts +1 -0
  99. package/lib/components/Request/__tests__/RequestDetails.test.js +98 -0
  100. package/lib/components/RequestSamples/__tests__/Example.test.d.ts +1 -0
  101. package/lib/components/RequestSamples/__tests__/Example.test.js +384 -0
  102. package/lib/components/RequestSamples/__tests__/RequestSamples.test.d.ts +1 -0
  103. package/lib/components/RequestSamples/__tests__/RequestSamples.test.js +226 -0
  104. package/lib/components/RequestSamples/__tests__/useCodeSamples.test.d.ts +1 -0
  105. package/lib/components/RequestSamples/__tests__/useCodeSamples.test.js +64 -0
  106. package/lib/components/ResponseSamples/__tests__/ResponseSamples.test.d.ts +1 -0
  107. package/lib/components/ResponseSamples/__tests__/ResponseSamples.test.js +29 -0
  108. package/lib/components/Responses/OperationResponseList.js +1 -1
  109. package/lib/components/Responses/__tests__/OperationResponseList.test.d.ts +1 -0
  110. package/lib/components/Responses/__tests__/OperationResponseList.test.js +89 -0
  111. package/lib/components/Responses/__tests__/ResponseDetails.test.d.ts +1 -0
  112. package/lib/components/Responses/__tests__/ResponseDetails.test.js +111 -0
  113. package/lib/components/Responses/__tests__/ResponsesHeaders.test.d.ts +1 -0
  114. package/lib/components/Responses/__tests__/ResponsesHeaders.test.js +26 -0
  115. package/lib/components/Schema/Schema.js +1 -1
  116. package/lib/components/Schema/SubSchema.js +1 -1
  117. package/lib/components/Schema/__tests__/ArraySchema.test.d.ts +1 -0
  118. package/lib/components/Schema/__tests__/ArraySchema.test.js +93 -0
  119. package/lib/components/Schema/__tests__/ObjectSchema.test.d.ts +1 -0
  120. package/lib/components/Schema/__tests__/ObjectSchema.test.js +115 -0
  121. package/lib/components/Schema/__tests__/OneOfSchema.test.d.ts +1 -0
  122. package/lib/components/Schema/__tests__/OneOfSchema.test.js +33 -0
  123. package/lib/components/Schema/__tests__/Schema.test.d.ts +1 -0
  124. package/lib/components/Schema/__tests__/Schema.test.js +67 -0
  125. package/lib/components/Schema/__tests__/useOneOfLocationIdx.test.d.ts +1 -0
  126. package/lib/components/Schema/__tests__/useOneOfLocationIdx.test.js +22 -0
  127. package/lib/components/Schema/useOneOfLocationIdx.js +1 -1
  128. package/lib/components/SchemaCatalogLink/__tests__/SchemaCatalogLink.test.d.ts +1 -0
  129. package/lib/components/SchemaCatalogLink/__tests__/SchemaCatalogLink.test.js +95 -0
  130. package/lib/components/Security/__tests__/Security.test.d.ts +1 -0
  131. package/lib/components/Security/__tests__/Security.test.js +38 -0
  132. package/lib/components/Security/__tests__/SecurityButton.test.d.ts +1 -0
  133. package/lib/components/Security/__tests__/SecurityButton.test.js +92 -0
  134. package/lib/components/Security/__tests__/SecurityModal.test.d.ts +1 -0
  135. package/lib/components/Security/__tests__/SecurityModal.test.js +172 -0
  136. package/lib/components/ServerList/__tests__/ServerList.test.d.ts +1 -0
  137. package/lib/components/ServerList/__tests__/ServerList.test.js +83 -0
  138. package/lib/components/SideMenu/hooks/useMenuItems.js +1 -1
  139. package/lib/components/StickySidebar/StickyResponsiveSidebar.js +1 -1
  140. package/lib/components/Tabs/__tests__/Tabs.test.d.ts +1 -0
  141. package/lib/components/Tabs/__tests__/Tabs.test.js +27 -0
  142. package/lib/components/TagItem/OperationsNavigation.js +1 -1
  143. package/lib/components/TagItem/TagItem.js +1 -1
  144. package/lib/components/ViewNested/__tests__/ViewNested.test.d.ts +1 -0
  145. package/lib/components/ViewNested/__tests__/ViewNested.test.js +42 -0
  146. package/lib/components/__tests__/Samples/ExampleSwitch.test.d.ts +1 -0
  147. package/lib/components/__tests__/Samples/ExampleSwitch.test.js +45 -0
  148. package/lib/components/__tests__/Samples/use-example-key.test.d.ts +1 -0
  149. package/lib/components/__tests__/Samples/use-example-key.test.js +28 -0
  150. package/lib/components/__tests__/common/ClearButton.test.d.ts +1 -0
  151. package/lib/components/__tests__/common/ClearButton.test.js +18 -0
  152. package/lib/components/__tests__/common/Dropdown.test.d.ts +1 -0
  153. package/lib/components/__tests__/common/Dropdown.test.js +52 -0
  154. package/lib/components/__tests__/mocks/examples.d.ts +4 -0
  155. package/lib/components/__tests__/mocks/examples.js +115 -0
  156. package/lib/components/common/LinkToField.js +1 -1
  157. package/lib/components/common/__tests__/Dropdown.test.d.ts +1 -0
  158. package/lib/components/common/__tests__/Dropdown.test.js +129 -0
  159. package/lib/components/common/__tests__/LinkToField.test.d.ts +1 -0
  160. package/lib/components/common/__tests__/LinkToField.test.js +39 -0
  161. package/lib/components/common/linkify.js +1 -1
  162. package/lib/hooks/useRouter.js +1 -1
  163. package/lib/hooks/useUppercase2LowercaseRedirect.js +1 -1
  164. package/lib/jotai/__tests__/app.test.d.ts +1 -0
  165. package/lib/jotai/__tests__/app.test.js +53 -0
  166. package/lib/models/__tests__/Callback.test.d.ts +1 -0
  167. package/lib/models/__tests__/Callback.test.js +15 -0
  168. package/lib/models/__tests__/FieldModel.test.d.ts +1 -0
  169. package/lib/models/__tests__/FieldModel.test.js +117 -0
  170. package/lib/models/__tests__/MediaContent.test.d.ts +1 -0
  171. package/lib/models/__tests__/MediaContent.test.js +105 -0
  172. package/lib/models/__tests__/Operation.test.d.ts +1 -0
  173. package/lib/models/__tests__/Operation.test.js +459 -0
  174. package/lib/models/__tests__/Response.test.d.ts +1 -0
  175. package/lib/models/__tests__/Response.test.js +221 -0
  176. package/lib/models/__tests__/Schema.circular.test.d.ts +1 -0
  177. package/lib/models/__tests__/Schema.circular.test.js +694 -0
  178. package/lib/models/__tests__/Schema.test.d.ts +1 -0
  179. package/lib/models/__tests__/Schema.test.js +1395 -0
  180. package/lib/models/__tests__/example.test.d.ts +1 -0
  181. package/lib/models/__tests__/example.test.js +90 -0
  182. package/lib/models/__tests__/group.test.d.ts +1 -0
  183. package/lib/models/__tests__/group.test.js +52 -0
  184. package/lib/models/__tests__/helpers.d.ts +5 -0
  185. package/lib/models/__tests__/helpers.js +62 -0
  186. package/lib/models/__tests__/request.test.d.ts +1 -0
  187. package/lib/models/__tests__/request.test.js +119 -0
  188. package/lib/services/__tests__/OpenAPIParser.test.d.ts +1 -0
  189. package/lib/services/__tests__/OpenAPIParser.test.js +80 -0
  190. package/lib/services/__tests__/check.test.d.ts +1 -0
  191. package/lib/services/__tests__/check.test.js +22 -0
  192. package/lib/services/__tests__/utils.test.d.ts +1 -0
  193. package/lib/services/__tests__/utils.test.js +42 -0
  194. package/lib/services/code-samples/__tests__/apply-environments.test.d.ts +1 -0
  195. package/lib/services/code-samples/__tests__/apply-environments.test.js +64 -0
  196. package/lib/services/code-samples/__tests__/build-code-samples.test.d.ts +1 -0
  197. package/lib/services/code-samples/__tests__/build-code-samples.test.js +70 -0
  198. package/lib/services/code-samples/__tests__/convertSampleToString.test.d.ts +1 -0
  199. package/lib/services/code-samples/__tests__/convertSampleToString.test.js +116 -0
  200. package/lib/services/code-samples/__tests__/generator-data-value.test.d.ts +1 -0
  201. package/lib/services/code-samples/__tests__/generator-data-value.test.js +277 -0
  202. package/lib/services/code-samples/__tests__/generator-serialized-value.test.d.ts +1 -0
  203. package/lib/services/code-samples/__tests__/generator-serialized-value.test.js +258 -0
  204. package/lib/services/code-samples/__tests__/generator-value.test.d.ts +1 -0
  205. package/lib/services/code-samples/__tests__/generator-value.test.js +273 -0
  206. package/lib/services/code-samples/__tests__/generator.test.d.ts +249 -0
  207. package/lib/services/code-samples/__tests__/generator.test.js +1201 -0
  208. package/lib/services/code-samples/__tests__/get-example-value-by-mime-type.test.d.ts +1 -0
  209. package/lib/services/code-samples/__tests__/get-example-value-by-mime-type.test.js +31 -0
  210. package/lib/services/code-samples/httpsnippet/__tests__/device-authorization.test.d.ts +1 -0
  211. package/lib/services/code-samples/httpsnippet/__tests__/device-authorization.test.js +222 -0
  212. package/lib/services/code-samples/httpsnippet/helpers/__tests__/code-helpers.test.d.ts +1 -0
  213. package/lib/services/code-samples/httpsnippet/helpers/__tests__/code-helpers.test.js +129 -0
  214. package/lib/services/code-samples/httpsnippet/helpers/__tests__/string-utility.test.d.ts +1 -0
  215. package/lib/services/code-samples/httpsnippet/helpers/__tests__/string-utility.test.js +49 -0
  216. package/lib/services/code-samples/httpsnippet/targets/csharp/__tests__/httpclient.test.d.ts +1 -0
  217. package/lib/services/code-samples/httpsnippet/targets/csharp/__tests__/httpclient.test.js +172 -0
  218. package/lib/services/code-samples/httpsnippet/targets/csharpNewtonsoft/__tests__/httpclient.test.d.ts +1 -0
  219. package/lib/services/code-samples/httpsnippet/targets/csharpNewtonsoft/__tests__/httpclient.test.js +172 -0
  220. package/lib/services/code-samples/httpsnippet/targets/go/__tests__/native.test.d.ts +1 -0
  221. package/lib/services/code-samples/httpsnippet/targets/go/__tests__/native.test.js +130 -0
  222. package/lib/services/code-samples/httpsnippet/targets/java/__tests__/httpclient.test.d.ts +1 -0
  223. package/lib/services/code-samples/httpsnippet/targets/java/__tests__/httpclient.test.js +191 -0
  224. package/lib/services/code-samples/httpsnippet/targets/java8/__tests__/apachehttp.test.d.ts +1 -0
  225. package/lib/services/code-samples/httpsnippet/targets/java8/__tests__/apachehttp.test.js +172 -0
  226. package/lib/services/code-samples/httpsnippet/targets/javascript/__tests__/fetch.test.d.ts +1 -0
  227. package/lib/services/code-samples/httpsnippet/targets/javascript/__tests__/fetch.test.js +85 -0
  228. package/lib/services/code-samples/httpsnippet/targets/node/__tests__/fetch.test.d.ts +1 -0
  229. package/lib/services/code-samples/httpsnippet/targets/node/__tests__/fetch.test.js +85 -0
  230. package/lib/services/code-samples/httpsnippet/targets/php/__tests__/curl.test.d.ts +1 -0
  231. package/lib/services/code-samples/httpsnippet/targets/php/__tests__/curl.test.js +126 -0
  232. package/lib/services/code-samples/httpsnippet/targets/python/__tests__/requests.test.d.ts +1 -0
  233. package/lib/services/code-samples/httpsnippet/targets/python/__tests__/requests.test.js +105 -0
  234. package/lib/services/code-samples/httpsnippet/targets/r/__tests__/httr.test.d.ts +1 -0
  235. package/lib/services/code-samples/httpsnippet/targets/r/__tests__/httr.test.js +126 -0
  236. package/lib/services/code-samples/httpsnippet/targets/ruby/__tests__/native.test.d.ts +1 -0
  237. package/lib/services/code-samples/httpsnippet/targets/ruby/__tests__/native.test.js +129 -0
  238. package/lib/services/code-samples/httpsnippet/targets/shell/__tests__/curl.test.d.ts +1 -0
  239. package/lib/services/code-samples/httpsnippet/targets/shell/__tests__/curl.test.js +129 -0
  240. package/lib/services/config-options/__tests__/helpers.test.d.ts +1 -0
  241. package/lib/services/config-options/__tests__/helpers.test.js +234 -0
  242. package/lib/services/history/__tests__/helpers.test.d.ts +1 -0
  243. package/lib/services/history/__tests__/helpers.test.js +19 -0
  244. package/lib/services/menu/__tests__/buildNestedTagsItems.test.d.ts +1 -0
  245. package/lib/services/menu/__tests__/buildNestedTagsItems.test.js +109 -0
  246. package/lib/services/menu/__tests__/builder.test.d.ts +1 -0
  247. package/lib/services/menu/__tests__/builder.test.js +307 -0
  248. package/lib/services/menu/__tests__/operation.test.d.ts +1 -0
  249. package/lib/services/menu/__tests__/operation.test.js +240 -0
  250. package/lib/services/menu/__tests__/tags.test.d.ts +1 -0
  251. package/lib/services/menu/__tests__/tags.test.js +71 -0
  252. package/lib/telemetry/RedocTelemetry.js +31 -1
  253. package/lib/telemetry/__tests__/RedocTelemetry.test.d.ts +1 -0
  254. package/lib/telemetry/__tests__/RedocTelemetry.test.js +107 -0
  255. package/lib/testProviders.d.ts +6 -0
  256. package/lib/testProviders.js +14 -0
  257. package/lib/utils/__tests__/areArraysEqual.test.d.ts +1 -0
  258. package/lib/utils/__tests__/areArraysEqual.test.js +33 -0
  259. package/lib/utils/__tests__/argValuesHelpers.d.ts +1 -0
  260. package/lib/utils/__tests__/argValuesHelpers.js +56 -0
  261. package/lib/utils/__tests__/calculateMaxLength.test.d.ts +1 -0
  262. package/lib/utils/__tests__/calculateMaxLength.test.js +119 -0
  263. package/lib/utils/__tests__/configure-helpers.test.d.ts +1 -0
  264. package/lib/utils/__tests__/configure-helpers.test.js +356 -0
  265. package/lib/utils/__tests__/convertSwagger2OpenAPI.test.d.ts +1 -0
  266. package/lib/utils/__tests__/convertSwagger2OpenAPI.test.js +392 -0
  267. package/lib/utils/__tests__/debounce.test.d.ts +1 -0
  268. package/lib/utils/__tests__/debounce.test.js +54 -0
  269. package/lib/utils/__tests__/debug.test.d.ts +1 -0
  270. package/lib/utils/__tests__/debug.test.js +23 -0
  271. package/lib/utils/__tests__/dom.test.d.ts +1 -0
  272. package/lib/utils/__tests__/dom.test.js +108 -0
  273. package/lib/utils/__tests__/getBreadcrumbs.test.d.ts +1 -0
  274. package/lib/utils/__tests__/getBreadcrumbs.test.js +98 -0
  275. package/lib/utils/__tests__/hasNestedFields.test.d.ts +1 -0
  276. package/lib/utils/__tests__/hasNestedFields.test.js +147 -0
  277. package/lib/utils/__tests__/helpers.test.d.ts +1 -0
  278. package/lib/utils/__tests__/helpers.test.js +174 -0
  279. package/lib/utils/__tests__/isMobile.test.d.ts +1 -0
  280. package/lib/utils/__tests__/isMobile.test.js +28 -0
  281. package/lib/utils/__tests__/loadAndBundleSpec.test.d.ts +1 -0
  282. package/lib/utils/__tests__/loadAndBundleSpec.test.js +22 -0
  283. package/lib/utils/__tests__/local-storage.test.d.ts +1 -0
  284. package/lib/utils/__tests__/local-storage.test.js +48 -0
  285. package/lib/utils/__tests__/object.test.d.ts +1 -0
  286. package/lib/utils/__tests__/object.test.js +45 -0
  287. package/lib/utils/__tests__/openapi.test.d.ts +1 -0
  288. package/lib/utils/__tests__/openapi.test.js +1378 -0
  289. package/lib/utils/__tests__/path.test.d.ts +1 -0
  290. package/lib/utils/__tests__/path.test.js +16 -0
  291. package/lib/utils/__tests__/queryString.test.d.ts +1 -0
  292. package/lib/utils/__tests__/queryString.test.js +60 -0
  293. package/lib/utils/__tests__/replaceVariables.test.d.ts +1 -0
  294. package/lib/utils/__tests__/replaceVariables.test.js +46 -0
  295. package/lib/utils/__tests__/simplifyAstStructure.test.d.ts +1 -0
  296. package/lib/utils/__tests__/simplifyAstStructure.test.js +26 -0
  297. package/lib/utils/__tests__/sort.test.d.ts +1 -0
  298. package/lib/utils/__tests__/sort.test.js +16 -0
  299. package/lib/utils/__tests__/string.test.d.ts +1 -0
  300. package/lib/utils/__tests__/string.test.js +16 -0
  301. package/lib/utils/__tests__/theme-helpers.test.d.ts +1 -0
  302. package/lib/utils/__tests__/theme-helpers.test.js +24 -0
  303. package/lib/utils/__tests__/url.test.d.ts +1 -0
  304. package/lib/utils/__tests__/url.test.js +134 -0
  305. package/lib/utils/path.d.ts +1 -1
  306. package/package.json +12 -12
  307. package/dist/redocly-openapi-docs.min.ai-chat-mappers-MY79QAeW.js +0 -1
  308. package/dist/redocly-openapi-docs.min.external-resolver-3KMJv7SC.js +0 -2
  309. package/dist/redocly-openapi-docs.min.index-BYVMr_la.js +0 -1
  310. package/dist/redocly-openapi-docs.min.index-CsqzTi3Z.js +0 -7586
  311. package/dist/redocly-openapi-docs.min.index-D8F7x0S6.js +0 -1
  312. package/dist/redocly-openapi-docs.min.index-qqKTpI_q.js +0 -1
  313. package/dist/redocly-openapi-docs.min.standalone-Ci6886Cr.js +0 -12114
  314. package/dist/redocly-openapi-docs.min.tauri-path-Bs1-AQjc.js +0 -1
@@ -0,0 +1,1395 @@
1
+ import { parseYaml } from '@redocly/openapi-core';
2
+ import { outdent } from 'outdent';
3
+ import { getMediaType } from '../mediaType.js';
4
+ import { getField } from '../field.js';
5
+ import { normalizeOptions, OpenAPIParser } from '../../services/index.js';
6
+ import { enumDetailsPrinter, printSchema } from './helpers.js';
7
+ import { getSchema } from '../schema.js';
8
+ // Fixture imports
9
+ import nestedEnumDescriptionSpec from './fixtures/nestedEnumDescroptionSample.json';
10
+ import discriminatorSpec from './fixtures/discriminator.json';
11
+ import discriminatorWithDefaultMappingSpec from './fixtures/discriminator-with-default-mapping.json';
12
+ import discriminatorDefaultOnlySpec from './fixtures/discriminator-default-only.json';
13
+ import discriminatorOrderedWithDefaultSpec from './fixtures/discriminator-ordered-with-default.json';
14
+ import oneOfTitlesSpec from './fixtures/oneOfTitles.json';
15
+ import conditionalSchemaSpec from './fixtures/3.1/conditionalSchema.json';
16
+ import conditionalFieldSpec from './fixtures/3.1/conditionalField.json';
17
+ import patternPropertiesSpec from './fixtures/3.1/patternProperties.json';
18
+ import prefixItemsSpec from './fixtures/3.1/prefixItems.json';
19
+ import arrayItemsSpec from './fixtures/arrayItems.json';
20
+ import fieldsSpec from './fixtures/fields.json';
21
+ // Map for test.each fixtures
22
+ const fixtureMap = {
23
+ './fixtures/3.1/prefixItems.json': prefixItemsSpec,
24
+ './fixtures/arrayItems.json': arrayItemsSpec,
25
+ };
26
+ const options = normalizeOptions({});
27
+ const deps = { operation: { pointer: 'testSchema' } };
28
+ describe('Models', () => {
29
+ describe('Schema', () => {
30
+ let parser;
31
+ test('parsing nested x-enumDescription', () => {
32
+ const spec = nestedEnumDescriptionSpec;
33
+ parser = new OpenAPIParser(spec, undefined, options);
34
+ const testSchema = spec.components?.schemas?.Test;
35
+ const schemaModel = getSchema({
36
+ parser,
37
+ schemaOrRef: testSchema,
38
+ pointer: '',
39
+ options,
40
+ deps,
41
+ });
42
+ // items with their own description render as a nested row which keeps the enum info
43
+ expect(schemaModel['x-enumDescriptions']).toBeUndefined();
44
+ expect(schemaModel.items?.['x-enumDescriptions']).toStrictEqual(testSchema?.items?.['x-enumDescriptions']);
45
+ expect(schemaModel.items?.enum).toEqual(testSchema?.items?.enum);
46
+ expect(schemaModel.isPrimitive).toBe(false);
47
+ });
48
+ test('discriminator with one field', () => {
49
+ const spec = discriminatorSpec;
50
+ parser = new OpenAPIParser(spec, undefined, options);
51
+ const schema = getSchema({
52
+ parser,
53
+ schemaOrRef: spec.components.schemas.Foo,
54
+ pointer: '',
55
+ options,
56
+ deps,
57
+ });
58
+ expect(schema.oneOf).toHaveLength(1);
59
+ expect(schema.discriminatorProp).toEqual('type');
60
+ });
61
+ test('discriminator with defaultMapping adds it as last item', () => {
62
+ const spec = discriminatorWithDefaultMappingSpec;
63
+ parser = new OpenAPIParser(spec, undefined, options);
64
+ const schema = getSchema({
65
+ parser,
66
+ schemaOrRef: spec.components.schemas.Pet,
67
+ pointer: '#/components/schemas/Pet',
68
+ options,
69
+ deps,
70
+ });
71
+ expect(schema.oneOf).toHaveLength(3);
72
+ expect(schema.oneOf?.[0].isDefaultMapping).toBe(false);
73
+ expect(schema.oneOf?.[0].title).toBe('cat');
74
+ expect(schema.oneOf?.[1].isDefaultMapping).toBe(false);
75
+ expect(schema.oneOf?.[1].title).toBe('dog');
76
+ expect(schema.oneOf?.[2].isDefaultMapping).toBe(true);
77
+ expect(schema.oneOf?.[2].title).toBe('Default mapping');
78
+ });
79
+ test('discriminator with only defaultMapping (no mapping)', () => {
80
+ const spec = discriminatorDefaultOnlySpec;
81
+ parser = new OpenAPIParser(spec, undefined, options);
82
+ const schema = getSchema({
83
+ parser,
84
+ schemaOrRef: spec.components.schemas.Animal,
85
+ pointer: '#/components/schemas/Animal',
86
+ options,
87
+ deps,
88
+ });
89
+ expect(schema.oneOf).toHaveLength(1);
90
+ expect(schema.oneOf?.[0].isDefaultMapping).toBe(true);
91
+ expect(schema.oneOf?.[0].title).toBe('Default mapping');
92
+ });
93
+ test('discriminator defaultMapping order preserved after sorting', () => {
94
+ const spec = discriminatorOrderedWithDefaultSpec;
95
+ parser = new OpenAPIParser(spec, undefined, options);
96
+ const schema = getSchema({
97
+ parser,
98
+ schemaOrRef: spec.components.schemas.Vehicle,
99
+ pointer: '#/components/schemas/Vehicle',
100
+ options,
101
+ deps,
102
+ });
103
+ expect(schema.oneOf).toHaveLength(4);
104
+ expect(schema.oneOf?.[0].title).toBe('truck');
105
+ expect(schema.oneOf?.[1].title).toBe('bike');
106
+ expect(schema.oneOf?.[2].title).toBe('car');
107
+ expect(schema.oneOf?.[3].title).toBe('Default mapping');
108
+ expect(schema.oneOf?.[3].isDefaultMapping).toBe(true);
109
+ });
110
+ test('oneOf/allOf titles', () => {
111
+ const spec = oneOfTitlesSpec;
112
+ parser = new OpenAPIParser(spec, undefined, options);
113
+ const schema = getSchema({
114
+ parser,
115
+ schemaOrRef: spec.components?.schemas?.Test,
116
+ pointer: '',
117
+ options,
118
+ deps,
119
+ });
120
+ expect(schema.fields).toHaveLength(3);
121
+ const anyOfField = schema.fields?.[0];
122
+ const oneOfField = schema.fields?.[1];
123
+ expect(anyOfField?.schema.displayType).toMatchInlineSnapshot(`"Foo (object) or Bar (object) or Base (object) or SpecificBase (object) or SpecificBase2 (object)"`);
124
+ expect(anyOfField?.schema.oneOf?.[0].title).toBe('Foo');
125
+ expect(anyOfField?.schema.oneOf?.[1].title).toBe('Bar');
126
+ expect(anyOfField?.schema.oneOf?.[2].title).toBe('Base');
127
+ expect(anyOfField?.schema.oneOf?.[3].title).toBe('SpecificBase');
128
+ expect(anyOfField?.schema.oneOf?.[4].title).toBe('SpecificBase2');
129
+ expect(oneOfField?.schema.displayType).toMatchInlineSnapshot(`"Foo (object) or Bar (object) or Base (object) or SpecificBase (object) or SpecificBase2 (object)"`);
130
+ expect(oneOfField?.schema.oneOf?.[0].title).toBe('Foo');
131
+ expect(oneOfField?.schema.oneOf?.[1].title).toBe('Bar');
132
+ expect(oneOfField?.schema.oneOf?.[2].title).toBe('Base');
133
+ expect(oneOfField?.schema.oneOf?.[3].title).toBe('SpecificBase');
134
+ expect(oneOfField?.schema.oneOf?.[4].title).toBe('SpecificBase2');
135
+ });
136
+ test('oneOf/allOf titles with hideSchemaTitles', () => {
137
+ const spec = oneOfTitlesSpec;
138
+ const options = normalizeOptions({
139
+ hideSchemaTitles: true,
140
+ });
141
+ parser = new OpenAPIParser(spec, undefined, options);
142
+ const schema = getSchema({
143
+ parser,
144
+ schemaOrRef: spec.components?.schemas?.Test,
145
+ pointer: '',
146
+ options,
147
+ deps,
148
+ });
149
+ expect(schema.fields).toHaveLength(3);
150
+ const anyOfField = schema.fields?.[0];
151
+ const oneOfField = schema.fields?.[1];
152
+ expect(anyOfField?.schema.displayType).toMatchInlineSnapshot(`"object"`);
153
+ expect(anyOfField?.schema.oneOf?.[0].title).toBe('Foo');
154
+ expect(anyOfField?.schema.oneOf?.[1].title).toBe('Bar');
155
+ expect(anyOfField?.schema.oneOf?.[2].title).toBe('Base');
156
+ expect(anyOfField?.schema.oneOf?.[3].title).toBe('SpecificBase');
157
+ expect(anyOfField?.schema.oneOf?.[4].title).toBe('SpecificBase2');
158
+ expect(oneOfField?.schema.displayType).toMatchInlineSnapshot(`"object"`);
159
+ expect(oneOfField?.schema.oneOf?.[0].title).toBe('Foo');
160
+ expect(oneOfField?.schema.oneOf?.[1].title).toBe('Bar');
161
+ expect(oneOfField?.schema.oneOf?.[2].title).toBe('Base');
162
+ expect(oneOfField?.schema.oneOf?.[3].title).toBe('SpecificBase');
163
+ expect(oneOfField?.schema.oneOf?.[4].title).toBe('SpecificBase2');
164
+ });
165
+ test('oneOf/allOf schema complex displayType', () => {
166
+ const spec = oneOfTitlesSpec;
167
+ parser = new OpenAPIParser(spec, undefined, options);
168
+ const schema = getSchema({
169
+ parser,
170
+ schemaOrRef: spec.components?.schemas?.WithArray,
171
+ pointer: '',
172
+ options,
173
+ deps,
174
+ });
175
+ expect(schema.oneOf).toHaveLength(2);
176
+ expect(schema.displayType).toBe('(Array of strings or numbers) or string');
177
+ });
178
+ test('oneOf/anyOf with pure $ref should NOT be marked as circular', () => {
179
+ const spec = parseYaml(outdent `
180
+ openapi: 3.1.0
181
+ components:
182
+ schemas:
183
+ ContactObject:
184
+ type: object
185
+ properties:
186
+ firstName:
187
+ type: string
188
+ lastName:
189
+ type: string
190
+ Customer:
191
+ type: object
192
+ properties:
193
+ primaryAddressOneOf:
194
+ description: Customer's primary address
195
+ oneOf:
196
+ - $ref: '#/components/schemas/ContactObject'
197
+ - type: 'null'
198
+ primaryAddressAnyOf:
199
+ description: Customer's primary address
200
+ anyOf:
201
+ - $ref: '#/components/schemas/ContactObject'
202
+ - type: 'null'
203
+ `);
204
+ parser = new OpenAPIParser(spec, undefined, options);
205
+ const schema = getSchema({
206
+ parser,
207
+ schemaOrRef: spec.components?.schemas?.Customer,
208
+ pointer: '#/components/schemas/Customer',
209
+ options,
210
+ deps,
211
+ });
212
+ expect(schema.isCircular).toBe(false);
213
+ const oneOfField = schema.fields?.find((f) => f.name === 'primaryAddressOneOf');
214
+ expect(oneOfField).toBeDefined();
215
+ expect(oneOfField?.schema.oneOf).toBeDefined();
216
+ expect(oneOfField?.schema.oneOf?.length).toBe(2);
217
+ oneOfField?.schema.oneOf?.forEach((variant) => {
218
+ expect(variant.isCircular).toBe(false);
219
+ });
220
+ const anyOfField = schema.fields?.find((f) => f.name === 'primaryAddressAnyOf');
221
+ expect(anyOfField).toBeDefined();
222
+ expect(anyOfField?.schema.oneOf).toBeDefined();
223
+ expect(anyOfField?.schema.oneOf?.length).toBe(2);
224
+ anyOfField?.schema.oneOf?.forEach((variant) => {
225
+ expect(variant.isCircular).toBe(false);
226
+ });
227
+ });
228
+ test('oneOf/anyOf with circular reference should be detected', () => {
229
+ const spec = parseYaml(outdent `
230
+ openapi: 3.1.0
231
+ components:
232
+ schemas:
233
+ TreeNode:
234
+ type: object
235
+ properties:
236
+ value:
237
+ type: string
238
+ nextOneOf:
239
+ oneOf:
240
+ - $ref: '#/components/schemas/TreeNode'
241
+ - type: 'null'
242
+ nextAnyOf:
243
+ anyOf:
244
+ - $ref: '#/components/schemas/TreeNode'
245
+ - type: 'null'
246
+ `);
247
+ parser = new OpenAPIParser(spec, undefined, options);
248
+ const schema = getSchema({
249
+ parser,
250
+ schemaOrRef: spec.components?.schemas?.TreeNode,
251
+ pointer: '#/components/schemas/TreeNode',
252
+ options,
253
+ deps,
254
+ });
255
+ const oneOfField = schema.fields?.find((f) => f.name === 'nextOneOf');
256
+ expect(oneOfField).toBeDefined();
257
+ expect(oneOfField?.schema.oneOf).toBeDefined();
258
+ const oneOfCircularVariant = oneOfField?.schema.oneOf?.find((v) => v.isCircular);
259
+ expect(oneOfCircularVariant).toBeDefined();
260
+ const anyOfField = schema.fields?.find((f) => f.name === 'nextAnyOf');
261
+ expect(anyOfField).toBeDefined();
262
+ expect(anyOfField?.schema.oneOf).toBeDefined();
263
+ const anyOfCircularVariant = anyOfField?.schema.oneOf?.find((v) => v.isCircular);
264
+ expect(anyOfCircularVariant).toBeDefined();
265
+ });
266
+ test('schemaDefinition should resolve schema with conditional operators', () => {
267
+ const spec = conditionalSchemaSpec;
268
+ parser = new OpenAPIParser(spec, undefined, options);
269
+ const schema = getSchema({
270
+ parser,
271
+ schemaOrRef: spec.components?.schemas?.Test,
272
+ pointer: '',
273
+ options,
274
+ deps,
275
+ });
276
+ expect(schema.oneOf).toHaveLength(2);
277
+ expect(schema.oneOf?.[0].schema.title).toBe('=== 10');
278
+ expect(schema.oneOf?.[1].schema.title).toBe('case 2');
279
+ expect(schema.oneOf?.[0].schema).toMatchSnapshot();
280
+ expect(schema.oneOf?.[1].schema).toMatchSnapshot();
281
+ });
282
+ test('schemaDefinition should resolve field with conditional operators', () => {
283
+ const spec = conditionalFieldSpec;
284
+ parser = new OpenAPIParser(spec, undefined, options);
285
+ const schema = getSchema({
286
+ parser,
287
+ schemaOrRef: spec.components?.schemas?.Test,
288
+ pointer: '',
289
+ options,
290
+ deps,
291
+ });
292
+ expect(schema.fields).toHaveLength(1);
293
+ expect(schema.fields && schema.fields[0].schema.oneOf).toHaveLength(2);
294
+ expect(schema.fields && schema.fields[0].schema.oneOf?.[0].schema.title).toBe('isString');
295
+ expect(schema.fields && schema.fields[0].schema.oneOf?.[1].schema.title).toBe('notString');
296
+ expect(schema.fields && schema.fields[0].schema.oneOf?.[0].schema).toMatchSnapshot();
297
+ expect(schema.fields && schema.fields[0].schema.oneOf?.[1].schema).toMatchSnapshot();
298
+ });
299
+ test('schemaDefinition should resolve patternProperties', () => {
300
+ vi.spyOn(console, 'warn').mockImplementation(() => { });
301
+ const spec = patternPropertiesSpec;
302
+ parser = new OpenAPIParser(spec, undefined, {
303
+ ...options,
304
+ sortRequiredPropsFirst: true,
305
+ });
306
+ const schema = getSchema({
307
+ parser,
308
+ schemaOrRef: spec.components?.schemas?.Patterns,
309
+ pointer: '',
310
+ options: {
311
+ ...options,
312
+ sortRequiredPropsFirst: true,
313
+ },
314
+ deps,
315
+ });
316
+ expect(schema.fields).toHaveLength(5);
317
+ expect(schema.fields?.[0].kind).toEqual('field');
318
+ expect(schema.fields?.[0].name).toEqual('nestedObjectProp');
319
+ expect(schema.fields?.[0].schema.fields?.[0].kind).toEqual('patternProperties');
320
+ expect(schema.fields?.[1].kind).toEqual('field');
321
+ expect(schema.fields?.[1].name).toEqual('nestedArrayProp');
322
+ expect(schema.fields?.[1].schema.type).toEqual('array');
323
+ expect(schema.fields?.[1].schema.items?.fields?.[0].kind).toEqual('patternProperties');
324
+ expect(schema.fields?.[2].kind).toEqual('patternProperties');
325
+ expect(schema.fields?.[2].schema.type).toEqual('string');
326
+ expect(schema.fields?.[3].kind).toEqual('patternProperties');
327
+ expect(schema.fields?.[3].schema.type).toEqual('object');
328
+ expect(schema.fields?.[4].kind).toEqual('patternProperties');
329
+ expect(schema.fields?.[4].schema.type).toEqual('any');
330
+ });
331
+ describe('type array', () => {
332
+ function testImmutablePart(schema) {
333
+ expect(schema.minItems).toEqual(1);
334
+ expect(schema.maxItems).toEqual(10);
335
+ expect(schema.fields?.[0].schema.type).toEqual('string');
336
+ expect(schema.fields?.[1].schema.type).toEqual('number');
337
+ }
338
+ const eachArray = ['./fixtures/3.1/prefixItems.json', './fixtures/arrayItems.json'];
339
+ test.each(eachArray)('schemaDefinition should resolve prefixItems without additional items', (specFixture) => {
340
+ const spec = fixtureMap[specFixture];
341
+ const parser = new OpenAPIParser(spec, undefined, options);
342
+ const schema = getSchema({
343
+ parser,
344
+ schemaOrRef: spec.components?.schemas?.Case1,
345
+ pointer: '',
346
+ options,
347
+ deps,
348
+ });
349
+ testImmutablePart(schema);
350
+ expect(schema.fields).toHaveLength(3);
351
+ expect(schema.fields?.[2].name).toEqual('[2]');
352
+ expect(schema.fields?.[2].schema.pointer).toEqual('#/components/schemas/Cat');
353
+ expect(schema.fields?.[2].schema.type).toEqual('object');
354
+ });
355
+ test.each(eachArray)('schemaDefinition should resolve prefixItems with additional items', (specFixture) => {
356
+ const spec = fixtureMap[specFixture];
357
+ const parser = new OpenAPIParser(spec, undefined, options);
358
+ const schema = getSchema({
359
+ parser,
360
+ schemaOrRef: spec.components?.schemas?.Case2,
361
+ pointer: '',
362
+ options,
363
+ deps,
364
+ });
365
+ testImmutablePart(schema);
366
+ expect(schema.fields).toHaveLength(4);
367
+ expect(schema.fields?.[3].name).toEqual('[3...]');
368
+ expect(schema.fields?.[2].schema.type).toEqual('object');
369
+ expect(schema.fields?.[2].schema.pointer).toEqual('#/components/schemas/Cat');
370
+ expect(schema.fields?.[3].schema.type).toEqual('any');
371
+ });
372
+ test.each(eachArray)('schemaDefinition should resolve prefixItems with additional items with $ref', (specFixture) => {
373
+ const spec = fixtureMap[specFixture];
374
+ const parser = new OpenAPIParser(spec, undefined, options);
375
+ const schema = getSchema({
376
+ parser,
377
+ schemaOrRef: spec.components?.schemas?.Case3,
378
+ pointer: '',
379
+ options,
380
+ deps,
381
+ });
382
+ testImmutablePart(schema);
383
+ expect(schema.fields).toHaveLength(4);
384
+ expect(schema.fields?.[3].name).toEqual('[3...]');
385
+ expect(schema.fields?.[2].schema.type).toEqual('object');
386
+ expect(schema.fields?.[2].schema.pointer).toEqual('#/components/schemas/Cat');
387
+ expect(schema.fields?.[3].schema.type).toEqual('object');
388
+ expect(schema.fields?.[3].schema.pointer).toEqual('#/components/schemas/Dog');
389
+ });
390
+ test.each(eachArray)('schemaDefinition should resolve prefixItems with additional schema items', (specFixture) => {
391
+ const spec = fixtureMap[specFixture];
392
+ const parser = new OpenAPIParser(spec, undefined, options);
393
+ const schema = getSchema({
394
+ parser,
395
+ schemaOrRef: spec.components?.schemas?.Case4,
396
+ pointer: '',
397
+ options,
398
+ deps,
399
+ });
400
+ testImmutablePart(schema);
401
+ expect(schema.fields).toHaveLength(4);
402
+ expect(schema.fields?.[3].name).toEqual('[3...]');
403
+ expect(schema.fields?.[2].schema.type).toEqual('object');
404
+ expect(schema.fields?.[2].schema.pointer).toEqual('#/components/schemas/Cat');
405
+ expect(schema.fields?.[3].schema.type).toEqual('object');
406
+ });
407
+ test.each(eachArray)('schemaDefinition should resolve prefixItems with additional array items', (specFixture) => {
408
+ const spec = fixtureMap[specFixture];
409
+ const parser = new OpenAPIParser(spec, undefined, options);
410
+ const schema = getSchema({
411
+ parser,
412
+ schemaOrRef: spec.components?.schemas?.Case5,
413
+ pointer: '',
414
+ options,
415
+ deps,
416
+ });
417
+ testImmutablePart(schema);
418
+ expect(schema.fields).toHaveLength(4);
419
+ expect(schema.fields?.[3].name).toEqual('[3...]');
420
+ expect(schema.fields?.[2].schema.type).toEqual('object');
421
+ expect(schema.fields?.[2].schema.pointer).toEqual('#/components/schemas/Cat');
422
+ expect(schema.fields?.[3].schema.type).toEqual('array');
423
+ expect(schema.fields?.[3].schema.fields).toHaveLength(1);
424
+ expect(schema.fields?.[3].schema.fields?.[0].schema.type).toEqual('string');
425
+ expect(schema.fields?.[3].schema.fields?.[0].schema.constraints).toEqual([
426
+ '>= 0 characters',
427
+ ]);
428
+ });
429
+ test.each(eachArray)('schemaDefinition should resolve prefixItems with additional array items', (specFixture) => {
430
+ const spec = fixtureMap[specFixture];
431
+ const parser = new OpenAPIParser(spec, undefined, options);
432
+ const schema = getSchema({
433
+ parser,
434
+ schemaOrRef: spec.components?.schemas?.Case6,
435
+ pointer: '',
436
+ options,
437
+ deps,
438
+ });
439
+ expect(schema.type).toBe('array');
440
+ expect(schema.typePrefix).toBe('Array of ');
441
+ expect(schema.items?.fields).toHaveLength(2);
442
+ expect(schema.items?.pointer).toEqual('#/components/schemas/Tag');
443
+ expect(schema.isPrimitive).toBe(false);
444
+ expect(schema.items?.isPrimitive).toBe(false);
445
+ expect(schema.minItems).toBe(1);
446
+ });
447
+ test.each(eachArray)('schemaDefinition should resolve items with boolean type', (specFixture) => {
448
+ const spec = fixtureMap[specFixture];
449
+ const parser = new OpenAPIParser(spec, undefined, options);
450
+ const schema = getSchema({
451
+ parser,
452
+ schemaOrRef: spec.components?.schemas?.Case7,
453
+ pointer: '',
454
+ options,
455
+ deps,
456
+ });
457
+ expect(schema.fields?.[0].schema?.type).toBe('array');
458
+ expect(schema.fields?.[0].schema?.typePrefix).toBe('Array of ');
459
+ expect(schema.fields?.[0].schema.items?.displayType).toBe('any');
460
+ expect(schema?.fields).toHaveLength(1);
461
+ expect(schema.fields?.[0].schema.pointer).toEqual('#/components/schemas/AnyArray');
462
+ expect(schema.fields?.[0].schema.isPrimitive).toBe(true);
463
+ });
464
+ });
465
+ describe('array items info', () => {
466
+ const specWithRefItems = parseYaml(outdent `
467
+ openapi: 3.1.0
468
+ components:
469
+ schemas:
470
+ Collection:
471
+ type: object
472
+ required:
473
+ - owners
474
+ properties:
475
+ owners:
476
+ type: array
477
+ minItems: 1
478
+ maxItems: 20
479
+ description: List of groups which have write and read privileges over the collection.
480
+ items:
481
+ $ref: '#/components/schemas/AclGroup'
482
+ viewers:
483
+ type: array
484
+ items:
485
+ $ref: '#/components/schemas/AclGroup'
486
+ AclGroup:
487
+ type: string
488
+ format: email
489
+ maxLength: 256
490
+ pattern: ^[a-zA-Z0-9_+&*-]+@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$
491
+ description: OSDU Access Control List (ACL) group that controls data access.
492
+ `);
493
+ function getCollectionSchema() {
494
+ const parser = new OpenAPIParser(specWithRefItems, undefined, options);
495
+ return getSchema({
496
+ parser,
497
+ schemaOrRef: specWithRefItems.components?.schemas?.Collection,
498
+ pointer: '#/components/schemas/Collection',
499
+ options,
500
+ deps,
501
+ });
502
+ }
503
+ test('should keep only array-level info on the array schema and items info on the nested items schema', () => {
504
+ const schema = getCollectionSchema();
505
+ const owners = schema.fields?.find((f) => f.name === 'owners');
506
+ expect(owners?.schema.type).toEqual('array');
507
+ // the array row keeps only its own info
508
+ expect(owners?.schema.pattern).toBeUndefined();
509
+ expect(owners?.schema.format).toBeUndefined();
510
+ expect(owners?.schema.displayFormat).toBeFalsy();
511
+ expect(owners?.schema.title).toEqual('');
512
+ expect(owners?.schema.constraints).toEqual(['[ 1 .. 20 ] items']);
513
+ expect(owners?.schema.description).toEqual('List of groups which have write and read privileges over the collection.');
514
+ expect(owners?.description).toEqual('List of groups which have write and read privileges over the collection.');
515
+ // items with their own documentation make the array expandable
516
+ expect(owners?.schema.isPrimitive).toBe(false);
517
+ // the items info is rendered in the nested items row
518
+ expect(owners?.schema.items?.title).toEqual('AclGroup');
519
+ expect(owners?.schema.items?.pattern).toEqual('^[a-zA-Z0-9_+&*-]+@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$');
520
+ expect(owners?.schema.items?.format).toEqual('email');
521
+ expect(owners?.schema.items?.constraints).toEqual(['<= 256 characters']);
522
+ expect(owners?.schema.items?.description).toEqual('OSDU Access Control List (ACL) group that controls data access.');
523
+ });
524
+ test('array with no own description shows the items description only in the nested items row', () => {
525
+ const schema = getCollectionSchema();
526
+ const viewers = schema.fields?.find((f) => f.name === 'viewers');
527
+ expect(viewers?.schema.description).toEqual('');
528
+ expect(viewers?.description).toEqual('');
529
+ expect(viewers?.schema.constraints).toEqual([]);
530
+ expect(viewers?.schema.isPrimitive).toBe(false);
531
+ expect(viewers?.schema.items?.description).toEqual('OSDU Access Control List (ACL) group that controls data access.');
532
+ expect(viewers?.schema.items?.constraints).toEqual(['<= 256 characters']);
533
+ });
534
+ test('should keep the array own info when inline items have no extra info', () => {
535
+ const spec = parseYaml(outdent `
536
+ openapi: 3.1.0
537
+ components:
538
+ schemas:
539
+ Tags:
540
+ type: array
541
+ minItems: 1
542
+ description: List of tags.
543
+ items:
544
+ type: string
545
+ `);
546
+ const parser = new OpenAPIParser(spec, undefined, options);
547
+ const schema = getSchema({
548
+ parser,
549
+ schemaOrRef: spec.components?.schemas?.Tags,
550
+ pointer: '#/components/schemas/Tags',
551
+ options,
552
+ deps,
553
+ });
554
+ expect(schema.description).toEqual('List of tags.');
555
+ expect(schema.pattern).toBeUndefined();
556
+ expect(schema.format).toBeUndefined();
557
+ expect(schema.constraints).toEqual(['non-empty']);
558
+ // trivial items stay flattened into the array row
559
+ expect(schema.isPrimitive).toBe(true);
560
+ });
561
+ test('$ref sibling description should win over the referenced items description', () => {
562
+ const spec = parseYaml(outdent `
563
+ openapi: 3.1.0
564
+ components:
565
+ schemas:
566
+ Owners:
567
+ type: array
568
+ description: Description for property.
569
+ items:
570
+ $ref: '#/components/schemas/AclGroup'
571
+ description: Sibling description for items.
572
+ AclGroup:
573
+ type: string
574
+ maxLength: 256
575
+ description: OSDU Access Control List (ACL) group that controls data access.
576
+ `);
577
+ const parser = new OpenAPIParser(spec, undefined, options);
578
+ const schema = getSchema({
579
+ parser,
580
+ schemaOrRef: spec.components?.schemas?.Owners,
581
+ pointer: '#/components/schemas/Owners',
582
+ options,
583
+ deps,
584
+ });
585
+ expect(schema.description).toEqual('Description for property.');
586
+ expect(schema.items?.description).toEqual('Sibling description for items.');
587
+ });
588
+ test('$ref sibling description should win over the referenced items pre-parsed markdown description', () => {
589
+ // simulates Realm which pre-parses markdown descriptions into x-parsed-md-* extensions;
590
+ // plain-text descriptions (like the sibling one) are not pre-parsed
591
+ const spec = {
592
+ openapi: '3.1.0',
593
+ components: {
594
+ schemas: {
595
+ Owners: {
596
+ type: 'array',
597
+ items: {
598
+ $ref: '#/components/schemas/AclGroup',
599
+ description: 'Sibling description for items.',
600
+ },
601
+ },
602
+ AclGroup: {
603
+ type: 'string',
604
+ description: 'OSDU `ACL` group.',
605
+ 'x-parsed-md-description': { result: 'parsed markdoc ast of the ACL description' },
606
+ },
607
+ },
608
+ },
609
+ };
610
+ const parser = new OpenAPIParser(spec, undefined, options);
611
+ const schema = getSchema({
612
+ parser,
613
+ schemaOrRef: spec.components?.schemas?.Owners,
614
+ pointer: '#/components/schemas/Owners',
615
+ options,
616
+ deps,
617
+ });
618
+ expect(schema.items?.description).toEqual('Sibling description for items.');
619
+ });
620
+ test.each([
621
+ ['default', { type: 'string', default: 'admin' }],
622
+ ['const', { type: 'string', const: 'fixed' }],
623
+ ['deprecated', { type: 'string', deprecated: true }],
624
+ ['contentEncoding', { type: 'string', contentEncoding: 'base64' }],
625
+ ])('items with own %s render as a nested items row', (_keyword, items) => {
626
+ const parser = new OpenAPIParser({ openapi: '3.1.0' }, undefined, options);
627
+ const schema = getSchema({
628
+ parser,
629
+ schemaOrRef: { type: 'array', items },
630
+ pointer: '#/components/schemas/Test',
631
+ options,
632
+ deps,
633
+ });
634
+ expect(schema.isPrimitive).toBe(false);
635
+ });
636
+ test('items example is hoisted to the array row only when items have no own info', () => {
637
+ const parser = new OpenAPIParser({ openapi: '3.1.0' }, undefined, options);
638
+ // trivial items: the example is hoisted onto the array row
639
+ const flat = getSchema({
640
+ parser,
641
+ schemaOrRef: {
642
+ type: 'array',
643
+ items: { type: 'string', example: 'kuku.test' },
644
+ },
645
+ pointer: '#/components/schemas/Test',
646
+ options,
647
+ deps,
648
+ });
649
+ expect(flat.example).toEqual(['kuku.test']);
650
+ // documented items render as a nested row which shows the example itself
651
+ const rich = getSchema({
652
+ parser,
653
+ schemaOrRef: {
654
+ type: 'array',
655
+ items: { type: 'string', example: 'kuku.test', description: 'Items description.' },
656
+ },
657
+ pointer: '#/components/schemas/Test',
658
+ options,
659
+ deps,
660
+ });
661
+ expect(rich.example).toBeUndefined();
662
+ expect(rich.items?.example).toEqual('kuku.test');
663
+ });
664
+ test('object property own example wins over the parent object example entry', () => {
665
+ const parser = new OpenAPIParser({ openapi: '3.1.0' }, undefined, options);
666
+ const schema = getSchema({
667
+ parser,
668
+ schemaOrRef: {
669
+ type: 'object',
670
+ example: { id: 1, users: [] },
671
+ properties: {
672
+ id: { type: 'integer' },
673
+ users: {
674
+ type: 'array',
675
+ example: ['data.default.owners@opendes.testing.slb.com'],
676
+ items: { type: 'string' },
677
+ },
678
+ },
679
+ },
680
+ pointer: '#/components/schemas/Test',
681
+ options,
682
+ deps,
683
+ });
684
+ // the parent example fills properties without their own example
685
+ expect(schema.fields?.find((f) => f.name === 'id')?.example).toEqual(1);
686
+ // but never overrides a property's own example
687
+ expect(schema.fields?.find((f) => f.name === 'users')?.example).toEqual([
688
+ 'data.default.owners@opendes.testing.slb.com',
689
+ ]);
690
+ });
691
+ test('tuple array example moves to the item rows when it fits the tuple length', () => {
692
+ const parser = new OpenAPIParser({ openapi: '3.1.0' }, undefined, options);
693
+ const tupleSchema = {
694
+ type: 'array',
695
+ example: ['first', 42],
696
+ prefixItems: [{ type: 'string' }, { type: 'number' }],
697
+ };
698
+ const schema = getSchema({
699
+ parser,
700
+ schemaOrRef: tupleSchema,
701
+ pointer: '#/components/schemas/Test',
702
+ options,
703
+ deps,
704
+ });
705
+ expect(schema.example).toBeUndefined();
706
+ expect(schema.fields?.[0].example).toEqual('first');
707
+ expect(schema.fields?.[1].example).toEqual(42);
708
+ // falsy example values are still distributed to the item rows
709
+ const falsyExample = getSchema({
710
+ parser,
711
+ schemaOrRef: {
712
+ ...tupleSchema,
713
+ example: [0, false],
714
+ prefixItems: [{ type: 'number' }, { type: 'boolean' }],
715
+ },
716
+ pointer: '#/components/schemas/Test',
717
+ options,
718
+ deps,
719
+ });
720
+ expect(falsyExample.example).toBeUndefined();
721
+ expect(falsyExample.fields?.[0].example).toEqual(0);
722
+ expect(falsyExample.fields?.[1].example).toEqual(false);
723
+ // an explicit empty example has no entries to distribute and stays on the array row
724
+ const emptyExample = getSchema({
725
+ parser,
726
+ schemaOrRef: { ...tupleSchema, example: [] },
727
+ pointer: '#/components/schemas/Test',
728
+ options,
729
+ deps,
730
+ });
731
+ expect(emptyExample.example).toEqual([]);
732
+ expect(emptyExample.fields?.[0].example).toBeUndefined();
733
+ // an example longer than the tuple stays on the array row so no entries are lost,
734
+ // and is not also distributed to the item rows
735
+ const longExample = getSchema({
736
+ parser,
737
+ schemaOrRef: {
738
+ ...tupleSchema,
739
+ example: ['first', 42, 'extra'],
740
+ },
741
+ pointer: '#/components/schemas/Test',
742
+ options,
743
+ deps,
744
+ });
745
+ expect(longExample.example).toEqual(['first', 42, 'extra']);
746
+ expect(longExample.fields?.[0].example).toBeUndefined();
747
+ expect(longExample.fields?.[1].example).toBeUndefined();
748
+ });
749
+ test.each([
750
+ // no items schema means any items are accepted
751
+ [{ type: 'array' }, 'Array of any'],
752
+ // items: false permits no items, so no item type is advertised
753
+ [{ type: 'array', items: false }, 'Array of items'],
754
+ // the parent of an items-less nested array still holds arrays
755
+ [{ type: 'array', items: { type: 'array' } }, 'Array of arrays'],
756
+ ])('array display type for %j', (schemaOrRef, expected) => {
757
+ const parser = new OpenAPIParser({ openapi: '3.1.0' }, undefined, options);
758
+ const schema = getSchema({
759
+ parser,
760
+ schemaOrRef: schemaOrRef,
761
+ pointer: '#/components/schemas/Test',
762
+ options,
763
+ deps,
764
+ });
765
+ expect(schema.typePrefix + schema.displayType).toEqual(expected);
766
+ });
767
+ test('should not hoist items info when inline items are an object (non-primitive)', () => {
768
+ const spec = parseYaml(outdent `
769
+ openapi: 3.1.0
770
+ components:
771
+ schemas:
772
+ Members:
773
+ type: array
774
+ minItems: 1
775
+ description: List of members.
776
+ items:
777
+ type: object
778
+ description: A member of the museum.
779
+ maxProperties: 5
780
+ properties:
781
+ name:
782
+ type: string
783
+ `);
784
+ const parser = new OpenAPIParser(spec, undefined, options);
785
+ const schema = getSchema({
786
+ parser,
787
+ schemaOrRef: spec.components?.schemas?.Members,
788
+ pointer: '#/components/schemas/Members',
789
+ options,
790
+ deps,
791
+ });
792
+ expect(schema.description).toEqual('List of members.');
793
+ expect(schema.constraints).toEqual(['non-empty']);
794
+ expect(schema.items?.fields).toHaveLength(1);
795
+ expect(schema.items?.fields?.[0].name).toEqual('name');
796
+ });
797
+ });
798
+ test('content example should override the schema example on the parameter', () => {
799
+ const spec = fieldsSpec;
800
+ parser = new OpenAPIParser(spec, undefined, options);
801
+ const field = getField(parser, {
802
+ $ref: '#/components/parameters/queryParamWithContentExample',
803
+ }, '', options, deps);
804
+ expect(field.example).toEqual({ id: 'content example' });
805
+ const schema = getSchema({
806
+ parser,
807
+ schemaOrRef: field.schema.schema,
808
+ pointer: '',
809
+ options,
810
+ deps,
811
+ });
812
+ // a property's own example stays more specific than the distributed parent example
813
+ expect(schema.fields && schema.fields[0].example).toEqual('schema example');
814
+ });
815
+ test('should get correct fields data if it includes allOf', () => {
816
+ const spec = parseYaml(outdent `
817
+ openapi: 3.0.0
818
+ components:
819
+ schemas:
820
+ User:
821
+ allOf:
822
+ - type: object
823
+ properties:
824
+ name:
825
+ type: string
826
+ description: correct description name
827
+ readOnly: false
828
+ writeOnly: false
829
+ allOf:
830
+ - '#/components/schemas/NameField'
831
+ NameField:
832
+ description: name description
833
+ readOnly: true
834
+ writeOnly: true
835
+ `);
836
+ parser = new OpenAPIParser(spec, undefined, options);
837
+ const schema = getSchema({
838
+ parser,
839
+ schemaOrRef: spec.components.schemas.User,
840
+ pointer: '#/components/schemas/User',
841
+ options,
842
+ deps,
843
+ });
844
+ expect(schema.fields?.[0].schema?.readOnly).toBe(false);
845
+ expect(schema.fields?.[0].schema?.writeOnly).toBe(false);
846
+ expect(printSchema(schema)).toMatchInlineSnapshot(`
847
+ "name: <string> (correct description name)
848
+ allOf: <any>"
849
+ `);
850
+ });
851
+ test('memoizes fields so repeated access returns stable model identities', () => {
852
+ const spec = parseYaml(outdent `
853
+ openapi: 3.0.0
854
+ components:
855
+ schemas:
856
+ User:
857
+ type: object
858
+ properties:
859
+ name:
860
+ type: string
861
+ address:
862
+ type: object
863
+ properties:
864
+ city:
865
+ type: string
866
+ `);
867
+ parser = new OpenAPIParser(spec, undefined, options);
868
+ const schema = getSchema({
869
+ parser,
870
+ schemaOrRef: spec.components.schemas.User,
871
+ pointer: '#/components/schemas/User',
872
+ options,
873
+ deps,
874
+ });
875
+ // Same array and same child model instances across accesses — this is what
876
+ // lets React's memoization skip re-rendering unchanged subtrees.
877
+ expect(schema.fields).toBe(schema.fields);
878
+ expect(schema.fields?.[1].schema).toBe(schema.fields?.[1].schema);
879
+ expect(schema.fields?.[1].schema.fields).toBe(schema.fields?.[1].schema.fields);
880
+ });
881
+ test('should preserve readOnly on deep property overridden via allOf in a complex schema', () => {
882
+ const spec = parseYaml(outdent `
883
+ openapi: 3.0.0
884
+ components:
885
+ schemas:
886
+ ArticleType:
887
+ type: object
888
+ properties:
889
+ id:
890
+ type: string
891
+ name:
892
+ type: string
893
+ ArticleTypeForCreateEditArticle:
894
+ allOf:
895
+ - type: object
896
+ required: [id]
897
+ properties:
898
+ name:
899
+ readOnly: true
900
+ - $ref: '#/components/schemas/ArticleType'
901
+ Version:
902
+ type: object
903
+ properties:
904
+ id:
905
+ type: string
906
+ articleType:
907
+ $ref: '#/components/schemas/ArticleType'
908
+ VersionForCreateArticle:
909
+ allOf:
910
+ - type: object
911
+ required: [name]
912
+ properties:
913
+ articleType:
914
+ $ref: '#/components/schemas/ArticleTypeForCreateEditArticle'
915
+ - $ref: '#/components/schemas/Version'
916
+ Article:
917
+ type: object
918
+ properties:
919
+ versions:
920
+ type: array
921
+ items:
922
+ $ref: '#/components/schemas/Version'
923
+ CreateArticleSchema:
924
+ allOf:
925
+ - type: object
926
+ properties:
927
+ versions:
928
+ type: array
929
+ items:
930
+ $ref: '#/components/schemas/VersionForCreateArticle'
931
+ - $ref: '#/components/schemas/Article'
932
+ `);
933
+ parser = new OpenAPIParser(spec, undefined, options);
934
+ const schema = getSchema({
935
+ parser,
936
+ schemaOrRef: spec.components.schemas.CreateArticleSchema,
937
+ pointer: '#/components/schemas/CreateArticleSchema',
938
+ options,
939
+ deps,
940
+ });
941
+ const versions = schema.fields?.find((f) => f.name === 'versions');
942
+ const articleType = versions?.schema.items?.fields?.find((f) => f.name === 'articleType');
943
+ const name = articleType?.schema.fields?.find((f) => f.name === 'name');
944
+ expect(name).toBeDefined();
945
+ expect(name?.schema.readOnly).toBe(true);
946
+ });
947
+ describe('enum values', () => {
948
+ test('should get correct fields enum fields without duplication', () => {
949
+ const spec = parseYaml(outdent `
950
+ openapi: 3.0.0
951
+ components:
952
+ schemas:
953
+ StringField: { type: string, title: StringField, enum: [A, B, C] }
954
+ FieldA: { type: string, title: FieldA, enum: [A1, A2, A3] }
955
+ FieldB: { type: string, title: FieldB, enum: [B1, B2, B3] }
956
+ FieldC: { type: string, title: FieldC, enum: [C1, C2, C3] }
957
+ ObjectWithAllOf:
958
+ title: StringFilter
959
+ type: object
960
+ allOf:
961
+ - properties:
962
+ type: { type: string, enum: [STRING] }
963
+ field: { $ref: '#/components/schemas/StringField' }
964
+ required: [type, field, values]
965
+ - oneOf:
966
+ - properties:
967
+ field: { type: string, enum: [A] }
968
+ values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
969
+ - properties:
970
+ field: { type: string, enum: [B] }
971
+ values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
972
+ - properties:
973
+ field: { type: string, enum: [C] }
974
+ values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
975
+ ObjectWithOneOf:
976
+ title: StringFilter
977
+ type: object
978
+ properties:
979
+ type: { type: string, enum: [STRING] }
980
+ field: { $ref: '#/components/schemas/StringField' }
981
+ required: [type, field, values]
982
+ oneOf:
983
+ - properties:
984
+ field: { type: string, enum: [A] }
985
+ values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
986
+ - properties:
987
+ field: { type: string, enum: [B] }
988
+ values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
989
+ - properties:
990
+ field: { type: string, enum: [C] }
991
+ values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
992
+ `);
993
+ parser = new OpenAPIParser(spec, undefined, options);
994
+ const schemaWithOneOf = getSchema({
995
+ parser,
996
+ schemaOrRef: spec.components.schemas.ObjectWithOneOf,
997
+ pointer: '#/components/schemas/ObjectWithOneOf',
998
+ options,
999
+ deps,
1000
+ });
1001
+ expect(printSchema(schemaWithOneOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
1002
+ "oneOf
1003
+ StringFilter ->
1004
+ field*: <string>enum: [A,B,C]
1005
+ values*: [<string>enum: [A1,A2,A3]]
1006
+ type*: <string>enum: [STRING]
1007
+ StringFilter ->
1008
+ field*: <string>enum: [A,B,C]
1009
+ values*: [<string>enum: [B1,B2,B3]]
1010
+ type*: <string>enum: [STRING]
1011
+ StringFilter ->
1012
+ field*: <string>enum: [A,B,C]
1013
+ values*: [<string>enum: [C1,C2,C3]]
1014
+ type*: <string>enum: [STRING]"
1015
+ `);
1016
+ const schemaWithAllOf = getSchema({
1017
+ parser,
1018
+ schemaOrRef: spec.components.schemas.ObjectWithAllOf,
1019
+ pointer: '#/components/schemas/ObjectWithAllOf',
1020
+ options,
1021
+ deps,
1022
+ });
1023
+ expect(printSchema(schemaWithAllOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
1024
+ "oneOf
1025
+ StringFilter ->
1026
+ type*: <string>enum: [STRING]
1027
+ field*: <string>enum: [A,B,C]
1028
+ values*: [<string>enum: [A1,A2,A3]]
1029
+ StringFilter ->
1030
+ type*: <string>enum: [STRING]
1031
+ field*: <string>enum: [B,A,C]
1032
+ values*: [<string>enum: [B1,B2,B3]]
1033
+ StringFilter ->
1034
+ type*: <string>enum: [STRING]
1035
+ field*: <string>enum: [C,A,B]
1036
+ values*: [<string>enum: [C1,C2,C3]]"
1037
+ `);
1038
+ });
1039
+ test('should get correct fields enum limits', () => {
1040
+ const spec = parseYaml(outdent `
1041
+ openapi: 3.0.0
1042
+ components:
1043
+ schemas:
1044
+ StringField: { type: string, title: StringField, enum: [A, B, C] }
1045
+ FieldA: { type: string, title: FieldA, enum: [A1, A2, A3] }
1046
+ FieldB: { type: string, title: FieldB, enum: [B1, B2, B3] }
1047
+ FieldC: { type: string, title: FieldC, enum: [C1, C2, C3] }
1048
+ ObjectWithAllOf:
1049
+ title: StringFilter
1050
+ type: object
1051
+ allOf:
1052
+ - properties:
1053
+ type: { type: string, enum: [STRING] }
1054
+ required: [type, field, values]
1055
+ - oneOf:
1056
+ - properties:
1057
+ field: { type: string, enum: [A] }
1058
+ values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
1059
+ - properties:
1060
+ field: { type: string, enum: [B] }
1061
+ values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
1062
+ - properties:
1063
+ field: { type: string, enum: [C] }
1064
+ values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
1065
+ ObjectWithOneOf:
1066
+ title: StringFilter
1067
+ type: object
1068
+ properties:
1069
+ type: { type: string, enum: [STRING] }
1070
+ required: [type, field, values]
1071
+ oneOf:
1072
+ - properties:
1073
+ field: { type: string, enum: [A] }
1074
+ values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
1075
+ - properties:
1076
+ field: { type: string, enum: [B] }
1077
+ values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
1078
+ - properties:
1079
+ field: { type: string, enum: [C] }
1080
+ values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
1081
+ `);
1082
+ parser = new OpenAPIParser(spec, undefined, options);
1083
+ const schemaWithOneOf = getSchema({
1084
+ parser,
1085
+ schemaOrRef: spec.components.schemas.ObjectWithOneOf,
1086
+ pointer: '#/components/schemas/ObjectWithOneOf',
1087
+ options,
1088
+ deps,
1089
+ });
1090
+ expect(printSchema(schemaWithOneOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
1091
+ "oneOf
1092
+ StringFilter ->
1093
+ field*: <string>enum: [A]
1094
+ values*: [<string>enum: [A1,A2,A3]]
1095
+ type*: <string>enum: [STRING]
1096
+ StringFilter ->
1097
+ field*: <string>enum: [B]
1098
+ values*: [<string>enum: [B1,B2,B3]]
1099
+ type*: <string>enum: [STRING]
1100
+ StringFilter ->
1101
+ field*: <string>enum: [C]
1102
+ values*: [<string>enum: [C1,C2,C3]]
1103
+ type*: <string>enum: [STRING]"
1104
+ `);
1105
+ const schemaWithAllOf = getSchema({
1106
+ parser,
1107
+ schemaOrRef: spec.components.schemas.ObjectWithAllOf,
1108
+ pointer: '#/components/schemas/ObjectWithAllOf',
1109
+ options,
1110
+ deps,
1111
+ });
1112
+ expect(printSchema(schemaWithAllOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
1113
+ "oneOf
1114
+ StringFilter ->
1115
+ type*: <string>enum: [STRING]
1116
+ field*: <string>enum: [A]
1117
+ values*: [<string>enum: [A1,A2,A3]]
1118
+ StringFilter ->
1119
+ type*: <string>enum: [STRING]
1120
+ field*: <string>enum: [B]
1121
+ values*: [<string>enum: [B1,B2,B3]]
1122
+ StringFilter ->
1123
+ type*: <string>enum: [STRING]
1124
+ field*: <string>enum: [C]
1125
+ values*: [<string>enum: [C1,C2,C3]]"
1126
+ `);
1127
+ });
1128
+ });
1129
+ test('should get correct sibling inside schema type for openapi 3.1', () => {
1130
+ const spec = parseYaml(outdent `
1131
+ openapi: 3.1.0
1132
+ paths:
1133
+ /test:
1134
+ get:
1135
+ operationId: test
1136
+ responses:
1137
+ '200':
1138
+ content:
1139
+ application/json:
1140
+ schema:
1141
+ type: object
1142
+ properties:
1143
+ testAttr:
1144
+ description: Overridden description
1145
+ type: string
1146
+ $ref: '#/components/schemas/Test'
1147
+ components:
1148
+ schemas:
1149
+ Test:
1150
+ type: object
1151
+ description: Refed description
1152
+ `);
1153
+ parser = new OpenAPIParser(spec, undefined, options);
1154
+ const name = 'application/json';
1155
+ const mediaType = getMediaType(parser, name, true, spec.paths['/test'].get.responses['200'].content[name], options, deps);
1156
+ expect(printSchema(mediaType?.schema)).toMatchInlineSnapshot(`"testAttr: <object> (Overridden description)"`);
1157
+ });
1158
+ test('should not override schema in openapi 3.0', () => {
1159
+ const spec = parseYaml(outdent `
1160
+ openapi: 3.0.0
1161
+ paths:
1162
+ /test:
1163
+ get:
1164
+ operationId: test
1165
+ responses:
1166
+ '200':
1167
+ content:
1168
+ application/json:
1169
+ schema:
1170
+ type: object
1171
+ properties:
1172
+ testAttr:
1173
+ type: string
1174
+ description: Overridden description
1175
+ $ref: '#/components/schemas/Test'
1176
+ components:
1177
+ schemas:
1178
+ Test:
1179
+ type: object
1180
+ description: Refed description
1181
+ `);
1182
+ parser = new OpenAPIParser(spec, undefined, options);
1183
+ const name = 'application/json';
1184
+ const mediaType = getMediaType(parser, name, true, spec.paths['/test'].get.responses['200'].content[name], options, deps);
1185
+ expect(printSchema(mediaType?.schema)).toMatchInlineSnapshot(`"testAttr: <object> (Refed description)"`);
1186
+ });
1187
+ test('should correctly merge the types of props in an allOf', () => {
1188
+ const spec = parseYaml(outdent `
1189
+ openapi: 3.0.0
1190
+ components:
1191
+ schemas:
1192
+ value:
1193
+ allOf:
1194
+ - type: object
1195
+ properties:
1196
+ baseProp: { type: string }
1197
+ testProp: { type: boolean }
1198
+ - type: object
1199
+ properties:
1200
+ baseProp: { type: string }
1201
+ testProp: { type: number }
1202
+ `);
1203
+ parser = new OpenAPIParser(spec, undefined, options);
1204
+ const schema = getSchema({
1205
+ parser,
1206
+ schemaOrRef: spec.components.schemas.value,
1207
+ pointer: '#/components/schemas/value',
1208
+ options,
1209
+ deps,
1210
+ });
1211
+ expect(printSchema(schema)).toMatchInlineSnapshot(`
1212
+ "baseProp: <string>
1213
+ testProp: <number>"
1214
+ `);
1215
+ });
1216
+ // Required for JSON Schema Specification Draft 07, which is used by asyncapi-docs
1217
+ test('should handle array schema with items as an array', () => {
1218
+ const spec = parseYaml(outdent `
1219
+ openapi: 3.0.0
1220
+ components:
1221
+ schemas:
1222
+ BranchPayload:
1223
+ title: Branch created payload
1224
+ allOf:
1225
+ - type: object
1226
+ properties:
1227
+ subjects:
1228
+ type: array
1229
+ items:
1230
+ - type: object
1231
+ description: Summary of Branch resource.
1232
+ properties:
1233
+ uri:
1234
+ type: string
1235
+ format: uri
1236
+ readOnly: true
1237
+ required:
1238
+ - uri
1239
+ - type: object
1240
+ description: Summary of Branch resource.
1241
+ properties:
1242
+ id:
1243
+ type: string
1244
+ readOnly: true
1245
+ required:
1246
+ - id
1247
+ additionalItems: false
1248
+ minItems: 1
1249
+ maxItems: 1
1250
+ `);
1251
+ parser = new OpenAPIParser(spec, undefined, options);
1252
+ const schema = getSchema({
1253
+ parser,
1254
+ schemaOrRef: spec.components.schemas.BranchPayload,
1255
+ pointer: '#/components/schemas/BranchPayload',
1256
+ options,
1257
+ deps,
1258
+ });
1259
+ expect(printSchema(schema)).toMatchInlineSnapshot(`
1260
+ "subjects:
1261
+ [0]:
1262
+ uri*: <string>
1263
+ [1]:
1264
+ id*: <string>
1265
+ additionalItems: <any>
1266
+ minItems: <any>
1267
+ maxItems: <any>"
1268
+ `);
1269
+ });
1270
+ test('oneOf child titles should not be overridden by parent schema title via $ref', () => {
1271
+ const spec = {
1272
+ openapi: '3.1.0',
1273
+ components: {
1274
+ schemas: {
1275
+ DocumentMetadata: {
1276
+ type: 'object',
1277
+ properties: {
1278
+ entityMetadata: {
1279
+ $ref: '#/components/schemas/EntityMetadata',
1280
+ },
1281
+ },
1282
+ },
1283
+ EntityMetadata: {
1284
+ title: 'EntityMetadata',
1285
+ description: 'Metadata for associated entity of document.',
1286
+ type: 'object',
1287
+ oneOf: [
1288
+ { $ref: '#/components/schemas/PnrMetadataWrapper' },
1289
+ { $ref: '#/components/schemas/EventMetadataWrapper' },
1290
+ ],
1291
+ },
1292
+ PnrMetadataWrapper: {
1293
+ type: 'object',
1294
+ title: 'PnrMetadataWrapper',
1295
+ properties: {
1296
+ pnrMetadata: {
1297
+ type: 'string',
1298
+ },
1299
+ },
1300
+ },
1301
+ EventMetadataWrapper: {
1302
+ type: 'object',
1303
+ title: 'EventMetadataWrapper',
1304
+ properties: {
1305
+ eventMetadata: {
1306
+ type: 'string',
1307
+ },
1308
+ },
1309
+ },
1310
+ },
1311
+ },
1312
+ };
1313
+ parser = new OpenAPIParser(spec, undefined, options);
1314
+ const documentSchema = getSchema({
1315
+ parser,
1316
+ schemaOrRef: spec.components?.schemas?.DocumentMetadata,
1317
+ pointer: '#/components/schemas/DocumentMetadata',
1318
+ options,
1319
+ deps,
1320
+ });
1321
+ const entityMetadataField = documentSchema.fields?.find((f) => f.name === 'entityMetadata');
1322
+ expect(entityMetadataField).toBeDefined();
1323
+ expect(entityMetadataField?.schema.oneOf).toBeDefined();
1324
+ expect(entityMetadataField?.schema.oneOf).toHaveLength(2);
1325
+ expect(entityMetadataField?.schema.oneOf?.[0].title).toBe('PnrMetadataWrapper');
1326
+ expect(entityMetadataField?.schema.oneOf?.[1].title).toBe('EventMetadataWrapper');
1327
+ expect(entityMetadataField?.schema.oneOf?.[0].title).not.toBe('EntityMetadata');
1328
+ expect(entityMetadataField?.schema.oneOf?.[1].title).not.toBe('EntityMetadata');
1329
+ });
1330
+ test('oneOf with allOf $ref should preserve each variant own title', () => {
1331
+ const spec = {
1332
+ openapi: '3.0.0',
1333
+ components: {
1334
+ schemas: {
1335
+ CalloutCommon: {
1336
+ title: 'Callout - Without authentication',
1337
+ type: 'object',
1338
+ properties: {
1339
+ name: { type: 'string' },
1340
+ calloutBaseurl: { type: 'string' },
1341
+ },
1342
+ },
1343
+ CalloutBasicAuth: {
1344
+ title: 'Callout - Base authentication',
1345
+ allOf: [
1346
+ { $ref: '#/components/schemas/CalloutCommon' },
1347
+ {
1348
+ type: 'object',
1349
+ properties: {
1350
+ authUsername: { type: 'string' },
1351
+ authPassword: { type: 'string' },
1352
+ },
1353
+ },
1354
+ ],
1355
+ },
1356
+ CalloutOauth2: {
1357
+ title: 'Callout - OAuth 2.0 authentication',
1358
+ allOf: [
1359
+ { $ref: '#/components/schemas/CalloutCommon' },
1360
+ {
1361
+ type: 'object',
1362
+ properties: {
1363
+ oauthClientId: { type: 'string' },
1364
+ oauthClientSecret: { type: 'string' },
1365
+ },
1366
+ },
1367
+ ],
1368
+ },
1369
+ CalloutTemplateRequest: {
1370
+ oneOf: [
1371
+ { $ref: '#/components/schemas/CalloutCommon' },
1372
+ { $ref: '#/components/schemas/CalloutBasicAuth' },
1373
+ { $ref: '#/components/schemas/CalloutOauth2' },
1374
+ ],
1375
+ },
1376
+ },
1377
+ },
1378
+ };
1379
+ parser = new OpenAPIParser(spec, undefined, options);
1380
+ const schema = getSchema({
1381
+ parser,
1382
+ schemaOrRef: spec.components?.schemas?.CalloutTemplateRequest,
1383
+ pointer: '#/components/schemas/CalloutTemplateRequest',
1384
+ options,
1385
+ deps,
1386
+ });
1387
+ expect(schema.oneOf).toBeDefined();
1388
+ expect(schema.oneOf).toHaveLength(3);
1389
+ expect(schema.oneOf?.[0].title).toBe('Callout - Without authentication');
1390
+ expect(schema.oneOf?.[1].title).toBe('Callout - Base authentication');
1391
+ expect(schema.oneOf?.[2].title).toBe('Callout - OAuth 2.0 authentication');
1392
+ });
1393
+ });
1394
+ });
1395
+ //# sourceMappingURL=Schema.test.js.map