@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.
- package/dist/{redocly-openapi-docs.min.AiChatProvider-DcsGB2gP.js → redocly-openapi-docs.min.AiChatProvider-j-VDfFJ9.js} +3 -3
- package/dist/{redocly-openapi-docs.min.AiChatSqliteDBStorage-wCZA4usG.js → redocly-openapi-docs.min.AiChatSqliteDBStorage-BBRBmffc.js} +1 -1
- package/dist/{redocly-openapi-docs.min.AiPanel-jo7fqtSt.js → redocly-openapi-docs.min.AiPanel-DTzHqAiI.js} +116 -116
- package/dist/redocly-openapi-docs.min.FileWatcher-DDoyaS7A.js +1 -0
- package/dist/redocly-openapi-docs.min.Observable-D6wKbFwB.js +1 -0
- package/dist/redocly-openapi-docs.min.SemanticSearchService-DNFOPBZK.js +1 -0
- package/dist/{redocly-openapi-docs.min.SqliteDBStorage-B_f6WR8o.js → redocly-openapi-docs.min.SqliteDBStorage-Dy40Vq04.js} +1 -1
- package/dist/redocly-openapi-docs.min.TauriFileSystemAdapter-CpViFqJQ.js +1 -0
- package/dist/redocly-openapi-docs.min.TauriRootStorage-TCUrp2uB.js +1 -0
- package/dist/redocly-openapi-docs.min.ai-chat-mappers-CmX-8902.js +1 -0
- package/dist/redocly-openapi-docs.min.core-BYyFOtMX.js +1 -0
- package/dist/redocly-openapi-docs.min.external-resolver-BkceRyB4.js +2 -0
- package/dist/redocly-openapi-docs.min.index-BCcol5vU.js +1 -0
- package/dist/redocly-openapi-docs.min.index-C6uU_v-b.js +1 -0
- package/dist/redocly-openapi-docs.min.index-CmXZfuiZ.js +7730 -0
- package/dist/redocly-openapi-docs.min.index-DVWw0ICA.js +1 -0
- package/dist/redocly-openapi-docs.min.index-YnvLQkG_.js +1 -0
- package/dist/redocly-openapi-docs.min.index-xl_tBaHD.js +1 -0
- package/dist/redocly-openapi-docs.min.js +1 -1
- package/dist/{redocly-openapi-docs.min.lint-C-zlwxhp.js → redocly-openapi-docs.min.lint-2YpbCz3r.js} +69 -69
- package/dist/{redocly-openapi-docs.min.lint-graphql-qEh9cZHx.js → redocly-openapi-docs.min.lint-graphql-Bgfcu2tP.js} +1 -1
- package/dist/redocly-openapi-docs.min.periodic-revalidation-Dsp-n7ui.js +1 -0
- package/dist/redocly-openapi-docs.min.promise-map-limit-Db_42GvV.js +1 -0
- package/dist/{redocly-openapi-docs.min.respect-run-hfNPYQ9x.js → redocly-openapi-docs.min.respect-run-Ct8taisL.js} +1 -1
- package/dist/redocly-openapi-docs.min.standalone-BPCdJgtH.js +11995 -0
- package/dist/redocly-openapi-docs.min.tauri-path-CmqBCxGb.js +1 -0
- package/dist/{redocly-openapi-docs.min.useAiChatQueries-DgSsCKMW.js → redocly-openapi-docs.min.useAiChatQueries-t8oy8jik.js} +80 -80
- package/lib/components/ApiInfo/__tests__/ApiInfo.test.d.ts +1 -0
- package/lib/components/ApiInfo/__tests__/ApiInfo.test.js +46 -0
- package/lib/components/Callbacks/CallbackOperation.js +1 -1
- package/lib/components/Callbacks/__tests__/Callbacks.test.d.ts +1 -0
- package/lib/components/Callbacks/__tests__/Callbacks.test.js +46 -0
- package/lib/components/Content/__tests__/useAutoScroll.test.d.ts +1 -0
- package/lib/components/Content/__tests__/useAutoScroll.test.js +88 -0
- package/lib/components/Content/useAutoScroll.js +1 -1
- package/lib/components/ContentItem/__tests__/useIsExpanded.test.d.ts +1 -0
- package/lib/components/ContentItem/__tests__/useIsExpanded.test.js +123 -0
- package/lib/components/ContentItem/useIsExpanded.js +1 -1
- package/lib/components/ContentItems/ContentItems.js +1 -1
- package/lib/components/ContentItems/VirtualList.js +1 -1
- package/lib/components/ContentItems/__tests__/Items.test.d.ts +1 -0
- package/lib/components/ContentItems/__tests__/Items.test.js +66 -0
- package/lib/components/ContentItems/__tests__/VirtualList.test.d.ts +1 -0
- package/lib/components/ContentItems/__tests__/VirtualList.test.js +135 -0
- package/lib/components/ContentItems/useScrollOnRender.js +1 -1
- package/lib/components/Discriminator/__tests__/DiscriminatorDropdown.test.d.ts +1 -0
- package/lib/components/Discriminator/__tests__/DiscriminatorDropdown.test.js +63 -0
- package/lib/components/Download/__tests__/DownloadSpecification.test.d.ts +1 -0
- package/lib/components/Download/__tests__/DownloadSpecification.test.js +52 -0
- package/lib/components/ExpandAllButton/__tests__/ExpandAllButton.test.d.ts +1 -0
- package/lib/components/ExpandAllButton/__tests__/ExpandAllButton.test.js +60 -0
- package/lib/components/ExpandAllButton/__tests__/helpers.test.d.ts +1 -0
- package/lib/components/ExpandAllButton/__tests__/helpers.test.js +133 -0
- package/lib/components/Language/__tests__/LanguageDropdown.test.d.ts +1 -0
- package/lib/components/Language/__tests__/LanguageDropdown.test.js +23 -0
- package/lib/components/Markdown/__tests__/Markdown.test.d.ts +1 -0
- package/lib/components/Markdown/__tests__/Markdown.test.js +34 -0
- package/lib/components/McpOverview/__tests__/McpOverview.test.d.ts +1 -0
- package/lib/components/McpOverview/__tests__/McpOverview.test.js +66 -0
- package/lib/components/McpTool/__tests__/McpPrompt.test.d.ts +1 -0
- package/lib/components/McpTool/__tests__/McpPrompt.test.js +57 -0
- package/lib/components/McpTool/__tests__/McpResource.test.d.ts +1 -0
- package/lib/components/McpTool/__tests__/McpResource.test.js +81 -0
- package/lib/components/McpTool/__tests__/McpTool.test.d.ts +1 -0
- package/lib/components/McpTool/__tests__/McpTool.test.js +82 -0
- package/lib/components/MediaTypeSwitch/__tests__/MediaTypesSwitch.test.d.ts +1 -0
- package/lib/components/MediaTypeSwitch/__tests__/MediaTypesSwitch.test.js +79 -0
- package/lib/components/OperationItem/__tests__/OperationItem.test.d.ts +1 -0
- package/lib/components/OperationItem/__tests__/OperationItem.test.js +70 -0
- package/lib/components/OperationItem/__tests__/__mocks__/mock-intersection-observer.d.ts +16 -0
- package/lib/components/OperationItem/__tests__/__mocks__/mock-intersection-observer.js +42 -0
- package/lib/components/Overview/__tests__/Overview.test.d.ts +1 -0
- package/lib/components/Overview/__tests__/Overview.test.js +59 -0
- package/lib/components/PayloadSamples/__tests__/Example.test.d.ts +1 -0
- package/lib/components/PayloadSamples/__tests__/Example.test.js +36 -0
- package/lib/components/PayloadSamples/__tests__/ExampleValue.test.d.ts +1 -0
- package/lib/components/PayloadSamples/__tests__/ExampleValue.test.js +197 -0
- package/lib/components/PayloadSamples/__tests__/PayloadSamples.test.d.ts +1 -0
- package/lib/components/PayloadSamples/__tests__/PayloadSamples.test.js +38 -0
- package/lib/components/PropertyDetails/__tests__/Extensions.test.d.ts +1 -0
- package/lib/components/PropertyDetails/__tests__/Extensions.test.js +21 -0
- package/lib/components/PropertyDetails/__tests__/FieldDetail.test.d.ts +1 -0
- package/lib/components/PropertyDetails/__tests__/FieldDetail.test.js +52 -0
- package/lib/components/PropertyDetails/__tests__/FieldDetails.test.d.ts +1 -0
- package/lib/components/PropertyDetails/__tests__/FieldDetails.test.js +191 -0
- package/lib/components/PropertyDetails/__tests__/PropertyDetails.test.d.ts +1 -0
- package/lib/components/PropertyDetails/__tests__/PropertyDetails.test.js +365 -0
- package/lib/components/PropertyDetails/__tests__/cycleColorsByLevel.test.d.ts +1 -0
- package/lib/components/PropertyDetails/__tests__/cycleColorsByLevel.test.js +23 -0
- package/lib/components/RedoclyOpenAPIDocs/__tests__/AppProvider.test.d.ts +1 -0
- package/lib/components/RedoclyOpenAPIDocs/__tests__/AppProvider.test.js +16 -0
- package/lib/components/RedoclyOpenAPIDocs/__tests__/RedoclyOpenAPIDocs.test.d.ts +1 -0
- package/lib/components/RedoclyOpenAPIDocs/__tests__/RedoclyOpenAPIDocs.test.js +104 -0
- package/lib/components/RenderHook/__tests__/RenderHook.test.d.ts +1 -0
- package/lib/components/RenderHook/__tests__/RenderHook.test.js +15 -0
- package/lib/components/Replay/__tests__/utils.test.d.ts +1 -0
- package/lib/components/Replay/__tests__/utils.test.js +526 -0
- package/lib/components/Request/__tests__/RequestDetails.test.d.ts +1 -0
- package/lib/components/Request/__tests__/RequestDetails.test.js +98 -0
- package/lib/components/RequestSamples/__tests__/Example.test.d.ts +1 -0
- package/lib/components/RequestSamples/__tests__/Example.test.js +384 -0
- package/lib/components/RequestSamples/__tests__/RequestSamples.test.d.ts +1 -0
- package/lib/components/RequestSamples/__tests__/RequestSamples.test.js +226 -0
- package/lib/components/RequestSamples/__tests__/useCodeSamples.test.d.ts +1 -0
- package/lib/components/RequestSamples/__tests__/useCodeSamples.test.js +64 -0
- package/lib/components/ResponseSamples/__tests__/ResponseSamples.test.d.ts +1 -0
- package/lib/components/ResponseSamples/__tests__/ResponseSamples.test.js +29 -0
- package/lib/components/Responses/OperationResponseList.js +1 -1
- package/lib/components/Responses/__tests__/OperationResponseList.test.d.ts +1 -0
- package/lib/components/Responses/__tests__/OperationResponseList.test.js +89 -0
- package/lib/components/Responses/__tests__/ResponseDetails.test.d.ts +1 -0
- package/lib/components/Responses/__tests__/ResponseDetails.test.js +111 -0
- package/lib/components/Responses/__tests__/ResponsesHeaders.test.d.ts +1 -0
- package/lib/components/Responses/__tests__/ResponsesHeaders.test.js +26 -0
- package/lib/components/Schema/Schema.js +1 -1
- package/lib/components/Schema/SubSchema.js +1 -1
- package/lib/components/Schema/__tests__/ArraySchema.test.d.ts +1 -0
- package/lib/components/Schema/__tests__/ArraySchema.test.js +93 -0
- package/lib/components/Schema/__tests__/ObjectSchema.test.d.ts +1 -0
- package/lib/components/Schema/__tests__/ObjectSchema.test.js +115 -0
- package/lib/components/Schema/__tests__/OneOfSchema.test.d.ts +1 -0
- package/lib/components/Schema/__tests__/OneOfSchema.test.js +33 -0
- package/lib/components/Schema/__tests__/Schema.test.d.ts +1 -0
- package/lib/components/Schema/__tests__/Schema.test.js +67 -0
- package/lib/components/Schema/__tests__/useOneOfLocationIdx.test.d.ts +1 -0
- package/lib/components/Schema/__tests__/useOneOfLocationIdx.test.js +22 -0
- package/lib/components/Schema/useOneOfLocationIdx.js +1 -1
- package/lib/components/SchemaCatalogLink/__tests__/SchemaCatalogLink.test.d.ts +1 -0
- package/lib/components/SchemaCatalogLink/__tests__/SchemaCatalogLink.test.js +95 -0
- package/lib/components/Security/__tests__/Security.test.d.ts +1 -0
- package/lib/components/Security/__tests__/Security.test.js +38 -0
- package/lib/components/Security/__tests__/SecurityButton.test.d.ts +1 -0
- package/lib/components/Security/__tests__/SecurityButton.test.js +92 -0
- package/lib/components/Security/__tests__/SecurityModal.test.d.ts +1 -0
- package/lib/components/Security/__tests__/SecurityModal.test.js +172 -0
- package/lib/components/ServerList/__tests__/ServerList.test.d.ts +1 -0
- package/lib/components/ServerList/__tests__/ServerList.test.js +83 -0
- package/lib/components/SideMenu/hooks/useMenuItems.js +1 -1
- package/lib/components/StickySidebar/StickyResponsiveSidebar.js +1 -1
- package/lib/components/Tabs/__tests__/Tabs.test.d.ts +1 -0
- package/lib/components/Tabs/__tests__/Tabs.test.js +27 -0
- package/lib/components/TagItem/OperationsNavigation.js +1 -1
- package/lib/components/TagItem/TagItem.js +1 -1
- package/lib/components/ViewNested/__tests__/ViewNested.test.d.ts +1 -0
- package/lib/components/ViewNested/__tests__/ViewNested.test.js +42 -0
- package/lib/components/__tests__/Samples/ExampleSwitch.test.d.ts +1 -0
- package/lib/components/__tests__/Samples/ExampleSwitch.test.js +45 -0
- package/lib/components/__tests__/Samples/use-example-key.test.d.ts +1 -0
- package/lib/components/__tests__/Samples/use-example-key.test.js +28 -0
- package/lib/components/__tests__/common/ClearButton.test.d.ts +1 -0
- package/lib/components/__tests__/common/ClearButton.test.js +18 -0
- package/lib/components/__tests__/common/Dropdown.test.d.ts +1 -0
- package/lib/components/__tests__/common/Dropdown.test.js +52 -0
- package/lib/components/__tests__/mocks/examples.d.ts +4 -0
- package/lib/components/__tests__/mocks/examples.js +115 -0
- package/lib/components/common/LinkToField.js +1 -1
- package/lib/components/common/__tests__/Dropdown.test.d.ts +1 -0
- package/lib/components/common/__tests__/Dropdown.test.js +129 -0
- package/lib/components/common/__tests__/LinkToField.test.d.ts +1 -0
- package/lib/components/common/__tests__/LinkToField.test.js +39 -0
- package/lib/components/common/linkify.js +1 -1
- package/lib/hooks/useRouter.js +1 -1
- package/lib/hooks/useUppercase2LowercaseRedirect.js +1 -1
- package/lib/jotai/__tests__/app.test.d.ts +1 -0
- package/lib/jotai/__tests__/app.test.js +53 -0
- package/lib/models/__tests__/Callback.test.d.ts +1 -0
- package/lib/models/__tests__/Callback.test.js +15 -0
- package/lib/models/__tests__/FieldModel.test.d.ts +1 -0
- package/lib/models/__tests__/FieldModel.test.js +117 -0
- package/lib/models/__tests__/MediaContent.test.d.ts +1 -0
- package/lib/models/__tests__/MediaContent.test.js +105 -0
- package/lib/models/__tests__/Operation.test.d.ts +1 -0
- package/lib/models/__tests__/Operation.test.js +459 -0
- package/lib/models/__tests__/Response.test.d.ts +1 -0
- package/lib/models/__tests__/Response.test.js +221 -0
- package/lib/models/__tests__/Schema.circular.test.d.ts +1 -0
- package/lib/models/__tests__/Schema.circular.test.js +694 -0
- package/lib/models/__tests__/Schema.test.d.ts +1 -0
- package/lib/models/__tests__/Schema.test.js +1395 -0
- package/lib/models/__tests__/example.test.d.ts +1 -0
- package/lib/models/__tests__/example.test.js +90 -0
- package/lib/models/__tests__/group.test.d.ts +1 -0
- package/lib/models/__tests__/group.test.js +52 -0
- package/lib/models/__tests__/helpers.d.ts +5 -0
- package/lib/models/__tests__/helpers.js +62 -0
- package/lib/models/__tests__/request.test.d.ts +1 -0
- package/lib/models/__tests__/request.test.js +119 -0
- package/lib/services/__tests__/OpenAPIParser.test.d.ts +1 -0
- package/lib/services/__tests__/OpenAPIParser.test.js +80 -0
- package/lib/services/__tests__/check.test.d.ts +1 -0
- package/lib/services/__tests__/check.test.js +22 -0
- package/lib/services/__tests__/utils.test.d.ts +1 -0
- package/lib/services/__tests__/utils.test.js +42 -0
- package/lib/services/code-samples/__tests__/apply-environments.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/apply-environments.test.js +64 -0
- package/lib/services/code-samples/__tests__/build-code-samples.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/build-code-samples.test.js +70 -0
- package/lib/services/code-samples/__tests__/convertSampleToString.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/convertSampleToString.test.js +116 -0
- package/lib/services/code-samples/__tests__/generator-data-value.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/generator-data-value.test.js +277 -0
- package/lib/services/code-samples/__tests__/generator-serialized-value.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/generator-serialized-value.test.js +258 -0
- package/lib/services/code-samples/__tests__/generator-value.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/generator-value.test.js +273 -0
- package/lib/services/code-samples/__tests__/generator.test.d.ts +249 -0
- package/lib/services/code-samples/__tests__/generator.test.js +1201 -0
- package/lib/services/code-samples/__tests__/get-example-value-by-mime-type.test.d.ts +1 -0
- package/lib/services/code-samples/__tests__/get-example-value-by-mime-type.test.js +31 -0
- package/lib/services/code-samples/httpsnippet/__tests__/device-authorization.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/__tests__/device-authorization.test.js +222 -0
- package/lib/services/code-samples/httpsnippet/helpers/__tests__/code-helpers.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/helpers/__tests__/code-helpers.test.js +129 -0
- package/lib/services/code-samples/httpsnippet/helpers/__tests__/string-utility.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/helpers/__tests__/string-utility.test.js +49 -0
- package/lib/services/code-samples/httpsnippet/targets/csharp/__tests__/httpclient.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/csharp/__tests__/httpclient.test.js +172 -0
- package/lib/services/code-samples/httpsnippet/targets/csharpNewtonsoft/__tests__/httpclient.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/csharpNewtonsoft/__tests__/httpclient.test.js +172 -0
- package/lib/services/code-samples/httpsnippet/targets/go/__tests__/native.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/go/__tests__/native.test.js +130 -0
- package/lib/services/code-samples/httpsnippet/targets/java/__tests__/httpclient.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/java/__tests__/httpclient.test.js +191 -0
- package/lib/services/code-samples/httpsnippet/targets/java8/__tests__/apachehttp.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/java8/__tests__/apachehttp.test.js +172 -0
- package/lib/services/code-samples/httpsnippet/targets/javascript/__tests__/fetch.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/javascript/__tests__/fetch.test.js +85 -0
- package/lib/services/code-samples/httpsnippet/targets/node/__tests__/fetch.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/node/__tests__/fetch.test.js +85 -0
- package/lib/services/code-samples/httpsnippet/targets/php/__tests__/curl.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/php/__tests__/curl.test.js +126 -0
- package/lib/services/code-samples/httpsnippet/targets/python/__tests__/requests.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/python/__tests__/requests.test.js +105 -0
- package/lib/services/code-samples/httpsnippet/targets/r/__tests__/httr.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/r/__tests__/httr.test.js +126 -0
- package/lib/services/code-samples/httpsnippet/targets/ruby/__tests__/native.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/ruby/__tests__/native.test.js +129 -0
- package/lib/services/code-samples/httpsnippet/targets/shell/__tests__/curl.test.d.ts +1 -0
- package/lib/services/code-samples/httpsnippet/targets/shell/__tests__/curl.test.js +129 -0
- package/lib/services/config-options/__tests__/helpers.test.d.ts +1 -0
- package/lib/services/config-options/__tests__/helpers.test.js +234 -0
- package/lib/services/history/__tests__/helpers.test.d.ts +1 -0
- package/lib/services/history/__tests__/helpers.test.js +19 -0
- package/lib/services/menu/__tests__/buildNestedTagsItems.test.d.ts +1 -0
- package/lib/services/menu/__tests__/buildNestedTagsItems.test.js +109 -0
- package/lib/services/menu/__tests__/builder.test.d.ts +1 -0
- package/lib/services/menu/__tests__/builder.test.js +307 -0
- package/lib/services/menu/__tests__/operation.test.d.ts +1 -0
- package/lib/services/menu/__tests__/operation.test.js +240 -0
- package/lib/services/menu/__tests__/tags.test.d.ts +1 -0
- package/lib/services/menu/__tests__/tags.test.js +71 -0
- package/lib/telemetry/RedocTelemetry.js +31 -1
- package/lib/telemetry/__tests__/RedocTelemetry.test.d.ts +1 -0
- package/lib/telemetry/__tests__/RedocTelemetry.test.js +107 -0
- package/lib/testProviders.d.ts +6 -0
- package/lib/testProviders.js +14 -0
- package/lib/utils/__tests__/areArraysEqual.test.d.ts +1 -0
- package/lib/utils/__tests__/areArraysEqual.test.js +33 -0
- package/lib/utils/__tests__/argValuesHelpers.d.ts +1 -0
- package/lib/utils/__tests__/argValuesHelpers.js +56 -0
- package/lib/utils/__tests__/calculateMaxLength.test.d.ts +1 -0
- package/lib/utils/__tests__/calculateMaxLength.test.js +119 -0
- package/lib/utils/__tests__/configure-helpers.test.d.ts +1 -0
- package/lib/utils/__tests__/configure-helpers.test.js +356 -0
- package/lib/utils/__tests__/convertSwagger2OpenAPI.test.d.ts +1 -0
- package/lib/utils/__tests__/convertSwagger2OpenAPI.test.js +392 -0
- package/lib/utils/__tests__/debounce.test.d.ts +1 -0
- package/lib/utils/__tests__/debounce.test.js +54 -0
- package/lib/utils/__tests__/debug.test.d.ts +1 -0
- package/lib/utils/__tests__/debug.test.js +23 -0
- package/lib/utils/__tests__/dom.test.d.ts +1 -0
- package/lib/utils/__tests__/dom.test.js +108 -0
- package/lib/utils/__tests__/getBreadcrumbs.test.d.ts +1 -0
- package/lib/utils/__tests__/getBreadcrumbs.test.js +98 -0
- package/lib/utils/__tests__/hasNestedFields.test.d.ts +1 -0
- package/lib/utils/__tests__/hasNestedFields.test.js +147 -0
- package/lib/utils/__tests__/helpers.test.d.ts +1 -0
- package/lib/utils/__tests__/helpers.test.js +174 -0
- package/lib/utils/__tests__/isMobile.test.d.ts +1 -0
- package/lib/utils/__tests__/isMobile.test.js +28 -0
- package/lib/utils/__tests__/loadAndBundleSpec.test.d.ts +1 -0
- package/lib/utils/__tests__/loadAndBundleSpec.test.js +22 -0
- package/lib/utils/__tests__/local-storage.test.d.ts +1 -0
- package/lib/utils/__tests__/local-storage.test.js +48 -0
- package/lib/utils/__tests__/object.test.d.ts +1 -0
- package/lib/utils/__tests__/object.test.js +45 -0
- package/lib/utils/__tests__/openapi.test.d.ts +1 -0
- package/lib/utils/__tests__/openapi.test.js +1378 -0
- package/lib/utils/__tests__/path.test.d.ts +1 -0
- package/lib/utils/__tests__/path.test.js +16 -0
- package/lib/utils/__tests__/queryString.test.d.ts +1 -0
- package/lib/utils/__tests__/queryString.test.js +60 -0
- package/lib/utils/__tests__/replaceVariables.test.d.ts +1 -0
- package/lib/utils/__tests__/replaceVariables.test.js +46 -0
- package/lib/utils/__tests__/simplifyAstStructure.test.d.ts +1 -0
- package/lib/utils/__tests__/simplifyAstStructure.test.js +26 -0
- package/lib/utils/__tests__/sort.test.d.ts +1 -0
- package/lib/utils/__tests__/sort.test.js +16 -0
- package/lib/utils/__tests__/string.test.d.ts +1 -0
- package/lib/utils/__tests__/string.test.js +16 -0
- package/lib/utils/__tests__/theme-helpers.test.d.ts +1 -0
- package/lib/utils/__tests__/theme-helpers.test.js +24 -0
- package/lib/utils/__tests__/url.test.d.ts +1 -0
- package/lib/utils/__tests__/url.test.js +134 -0
- package/lib/utils/path.d.ts +1 -1
- package/package.json +12 -12
- package/dist/redocly-openapi-docs.min.ai-chat-mappers-MY79QAeW.js +0 -1
- package/dist/redocly-openapi-docs.min.external-resolver-3KMJv7SC.js +0 -2
- package/dist/redocly-openapi-docs.min.index-BYVMr_la.js +0 -1
- package/dist/redocly-openapi-docs.min.index-CsqzTi3Z.js +0 -7586
- package/dist/redocly-openapi-docs.min.index-D8F7x0S6.js +0 -1
- package/dist/redocly-openapi-docs.min.index-qqKTpI_q.js +0 -1
- package/dist/redocly-openapi-docs.min.standalone-Ci6886Cr.js +0 -12114
- 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
|