[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve hikaku\ntitle: ''\nlabels: Bug\nassignees: ''\n\n---\n\n# Setup information\n**hikaku version:**\n**specification converter:** \n**implementation converter:** \n**build tool and version:** `e.g. gradle 5.2.1, maven 3.5.3, ...`\n**test framework:** `e.g. junit 4.12, junit 5.4.0, testng 6.14.3...`\n\n# Describe the bug\nA clear and concise description of what the bug is.\n\n# Expected behavior\nA clear and concise description of what you expected to happen.\n\n# Code samples\nCan you provide specification snippets or code snippets?\n```\nCODE HERE\n```\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for hikaku\ntitle: ''\nlabels: Feature Request\nassignees: ''\n\n---\n\n**Is your feature request related to one or multiple existing converters?**\nIf related to converters, please list affected converters here.\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Additional context**\nAdd any other context, examples, snippets, links.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "content": "---\nname: Question\nabout: Got a question about hikaku for us?\ntitle: ''\nlabels: Question\nassignees: ''\n\n---\n\n\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"gradle\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".gitignore",
    "content": "# Custom\n\n**/out/\n\n\n# Created by https://www.gitignore.io/api/linux,macos,gradle,kotlin,windows,intellij,intellij+iml,intellij+all\n\n### Intellij ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff:\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/dictionaries\n\n# Sensitive or high-churn files:\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.xml\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n\n# Gradle:\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# CMake\ncmake-build-debug/\n\n# Mongo Explorer plugin:\n.idea/**/mongoSettings.xml\n\n## File-based project format:\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Cursive Clojure plugin\n.idea/replstate.xml\n\n# Ruby plugin and RubyMine\n/.rakeTasks\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n### Intellij Patch ###\n# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721\n\n# *.iml\n# modules.xml\n# .idea/misc.xml\n# *.ipr\n\n# Sonarlint plugin\n.idea/sonarlint\n\n### Intellij+all ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff:\n\n# Sensitive or high-churn files:\n\n# Gradle:\n\n# CMake\n\n# Mongo Explorer plugin:\n\n## File-based project format:\n\n## Plugin-specific files:\n\n# IntelliJ\n\n# mpeltonen/sbt-idea plugin\n\n# JIRA plugin\n\n# Cursive Clojure plugin\n\n# Ruby plugin and RubyMine\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\n\n### Intellij+all Patch ###\n# Ignores the whole .idea folder and all .iml files\n# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360\n\n.idea/\n\n# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023\n\n*.iml\nmodules.xml\n.idea/misc.xml\n*.ipr\n\n### Intellij+iml ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff:\n\n# Sensitive or high-churn files:\n\n# Gradle:\n\n# CMake\n\n# Mongo Explorer plugin:\n\n## File-based project format:\n\n## Plugin-specific files:\n\n# IntelliJ\n\n# mpeltonen/sbt-idea plugin\n\n# JIRA plugin\n\n# Cursive Clojure plugin\n\n# Ruby plugin and RubyMine\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\n\n### Intellij+iml Patch ###\n# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023\n\n\n### Kotlin ###\n# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n*.zip\n*.tar.gz\n*.rar\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n### Linux ###\n*~\n\n# temporary files which can be created if a process still has a handle open of a deleted file\n.fuse_hidden*\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n\n# .nfs files are created when an open file is removed but is still being accessed\n.nfs*\n\n### macOS ###\n*.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n### Windows ###\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n### Gradle ###\n.gradle\n**/build/\n\n# Ignore Gradle GUI config\ngradle-app.setting\n\n# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)\n!gradle-wrapper.jar\n\n# Cache of project\n.gradletasknamecache\n\n# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898\n# gradle/wrapper/gradle-wrapper.properties\n\n\n# End of https://www.gitignore.io/api/linux,macos,gradle,kotlin,windows,intellij,intellij+iml,intellij+all"
  },
  {
    "path": ".travis.yml",
    "content": "language: bash\nmatrix:\n  include:\n    - env: JDK=\"openjdk@1.11.0-2\"\n      os: linux\n      dist: trusty\n    - env: JDK=\"openjdk@1.11.0-2\"\n      os: windows\n    - env: JDK=\"openjdk@1.11.0-2\"\n      os: osx\nbefore_install:\n  - source install-jdk.sh\ninstall: true\nscript:\n  - ./gradlew clean test\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# hikaku\n[![Build Status](https://api.travis-ci.org/codecentric/hikaku.svg?branch=master)](https://travis-ci.org/codecentric/hikaku) [![Maven Central Version](https://img.shields.io/maven-central/v/de.codecentric.hikaku/hikaku-core.svg)](https://search.maven.org/search?q=g:de.codecentric.hikaku)\n\n<p align=\"center\">\n  <img src=\"docs/images/hikaku-logo-small.png\">\n</p>\n\nHikaku (比較) is japanese and means \"comparison\". This library tests if a REST-API implementation meets its specification.\n\nIf you create your REST-API contract-first without using any type of generation, you have to make sure that specification and implementation don't diverge.\nThe aim of this project is to meet this need and offer a mechanism to check specification and implementation for equality without having to create requests which are fired against a mock server. So this library won't check the behavior of the API, but the structural correctness. Please see also the section [limitations](#limitations)\n\n## Currently supported\n\n+ **Specifications**\n  + [OpenAPI 3.0.X](openapi/README.md)\n  + [RAML 1.X](raml/README.md)\n  + [WADL](wadl/README.md)\n+ **Implementations**\n  + [Spring MVC 5.3.X](spring/README.md)\n  + [Micronaut](micronaut/README.md)\n  + [JAX-RS 3.0.X](jax-rs/README.md)\n    + [Apache CXF](http://cxf.apache.org)\n    + [Dropwizard](https://www.dropwizard.io)\n    + [Jersey](https://jersey.github.io)\n    + [Resteasy](https://resteasy.github.io)\n    + [Restlet](https://restlet.com/open-source/documentation/user-guide/2.3/extensions/jaxrs)\n    + [Quarkus](https://quarkus.io)\n  \nPlease refer to the list of [all features](docs/features.md). To check the feature support for each converter.\nIt is possible that not every converter supports every feature. Only the intersection of the features of two `EndpointConverter`s is used for the matching. Please keep that in mind regarding the equality of implementation and specification.\n  \n## Usage\n\nSetting up a test with hikaku is very simple. You just instantiate the `Hikaku` class and provide an `EndpointConverter` for the specification and another one for the implementation. Optionally, you can also pass an instance of `HikakuConfig`. Check the list of options and default values of the [config](docs/config.md). Then you call `match()` on the `Hikaku` class.\nThe match result is sent to one or multiple `Reporter`. If the test fails kotlin's `DefaultAsserter.fail()` method is called.\n\n### Example\n\nThere is an artifact for each converter. So we need one dependency for the specification and one for the implementation. In this example our project consists of an OpenAPI specification and a Spring implementation. The specification does not contain the _/error_ endpoints created by spring, so we want to omit those.\nFirst add the dependencies for the converters, that we want to use. In this case `hikaku-openapi` and `hikaku-spring`.\n\n```gradle\ndependencies {\n    testImplementation \"de.codecentric.hikaku:hikaku-openapi:$hikakuVersion\"\n    testImplementation \"de.codecentric.hikaku:hikaku-spring:$hikakuVersion\"\n}\n```\n\n#### Kotlin\n\nAnd now we can create the test case:\n\n```kotlin\n@SpringBootTest\nclass SpecificationTest {\n\n    @Autowired\n    private lateinit var springContext: ApplicationContext\n\n    @Test\n    fun `specification matches implementation`() {\n        Hikaku(\n                specification = OpenApiConverter(Paths.get(\"openapi.yaml\")),\n                implementation = SpringConverter(springContext),\n                config = HikakuConfig(\n                        filters = listOf(SpringConverter.IGNORE_ERROR_ENDPOINT)\n                )\n        )\n        .match()\n    }\n}\n```\n\n#### Java\n\nSame example in Java:\n\n```java\n@SpringBootTest\npublic class SpecificationTest {\n\n  @Autowired\n  private ApplicationContext springContext;\n\n  @Test\n  public void specification_matches_implementation() {\n    List<Function1<Endpoint, Boolean>> filters = new ArrayList<>();\n    filters.add(SpringConverter.IGNORE_ERROR_ENDPOINT);\n\n    List<Reporter> reporters = new ArrayList<>();\n    reporters.add(new CommandLineReporter());\n\n    new Hikaku(\n            new OpenApiConverter(Paths.get(\"openapi.json\")),\n            new SpringConverter(springContext),\n            new HikakuConfig(\n                    reporters,\n                    filters\n            )\n    )\n    .match();\n  }\n}\n```\n\n## Limitations\nHikaku checks the implementation with static code analysis. So everything that is highly dynamic is not covered by hikaku. There might be other libraries and frameworks that can cover these aspects by checking the behavior.\n\n### http status codes\nFor implementations the status codes are very dynamic. There are various ways to set a http status. For example using a `ResponseEntity` object in spring or using additional filters and so on. That's why hikaku does not support http status codes.\n\n### Request and response object\nFor implementations both request and response objects are highly dynamic. For response objects there might be a generic `ResponseEntity` as well or interfaces with different implementations can be used. In both cases (request and response) the objects can be altered by a serialization library and there a lot of different libs out there. That's why hikaku neither supports request nor response objects.\n\n## More Info\n\n* **Blog (english):** [Spotting mismatches between your spec and your REST-API with hikaku](https://blog.codecentric.de/en/2019/03/spot-mismatches-between-your-spec-and-your-rest-api/)\n* **Blog (german):** [ Abweichungen zwischen Spezifikation und REST-API mit hikaku erkennen](https://blog.codecentric.de/2019/03/abweichungen-zwischen-rest-api-spezifikation-erkennen/)\n* **Sample project** [A complete sample project](https://github.com/cc-jhr/hikaku-sample)\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    ext {\n        kotlinVersion = '1.5.21'\n        jvmVersion = '1.8'\n    }\n\n    repositories {\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion\"\n    }\n}\n\nplugins {\n    id 'com.github.ben-manes.versions' version '0.39.0'\n}\n\nsubprojects {\n    apply plugin: 'idea'\n    apply plugin: 'maven'\n    apply plugin: 'signing'\n    apply plugin: 'kotlin'\n    apply plugin: 'java-library'\n\n    version = '3.2.1-SNAPSHOT'\n    sourceCompatibility = jvmVersion\n    targetCompatibility = jvmVersion\n\n    compileKotlin {\n        kotlinOptions {\n            freeCompilerArgs = ['-Xjsr305=strict']\n            jvmTarget = jvmVersion\n        }\n    }\n\n    compileTestKotlin {\n        kotlinOptions {\n            freeCompilerArgs = ['-Xjsr305=strict']\n            jvmTarget = jvmVersion\n        }\n    }\n\n    repositories {\n        mavenCentral()\n    }\n\n    dependencies {\n        api \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion\"\n        api \"org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion\"\n        api \"org.jetbrains.kotlin:kotlin-test:$kotlinVersion\"\n\n        testImplementation 'org.junit.platform:junit-platform-launcher:1.7.2'\n        testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'\n        testImplementation \"org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion\"\n        testImplementation 'org.assertj:assertj-core:3.20.2'\n    }\n\n    test {\n        useJUnitPlatform()\n    }\n\n    task javadocJar(type: Jar) {\n        archiveClassifier = 'javadoc'\n        from javadoc\n    }\n\n    task sourcesJar(type: Jar) {\n        archiveClassifier = 'sources'\n        from sourceSets.main.allSource\n    }\n\n    artifacts {\n        archives javadocJar, sourcesJar\n    }\n\n    signing {\n        sign configurations.archives\n    }\n\n    uploadArchives {\n        repositories {\n            mavenDeployer {\n                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n                repository(url: \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\") {\n                    authentication(userName: findProperty('ossrhUsername'), password: findProperty('ossrhPassword'))\n                }\n\n                snapshotRepository(url: \"https://oss.sonatype.org/content/repositories/snapshots/\") {\n                    authentication(userName: findProperty('ossrhUsername'), password: findProperty('ossrhPassword'))\n                }\n\n                pom.project {\n                    packaging = 'jar'\n\n                    url ='https://github.com/codecentric/hikaku'\n\n                    scm {\n                        connection = 'scm:git:git://github.com/codecentric/hikaku.git'\n                        developerConnection = 'scm:git:ssh://git@github.com:codecentric/hikaku.git'\n                        url = 'https://github.com/codecentric/hikaku'\n                    }\n\n                    licenses {\n                        license {\n                            name = 'Apache License, Version 2.0'\n                            url = 'http://www.apache.org/licenses/LICENSE-2.0'\n                        }\n                    }\n\n                    developers {\n                        developer {\n                            id = 'cc-jhr'\n                            name = 'Jannes Heinrich'\n                            email = '34243889+cc-jhr@users.noreply.github.com'\n                        }\n                        developer {\n                            id = 'lmller'\n                            name = 'Lovis Möller'\n                            email = 'lovis.moeller@codecentric.de'\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/build.gradle",
    "content": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-core'\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-core'\n        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains the core elements which can be used to create additional converters and reporters.'\n      }\n    }\n  }\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/Hikaku.kt",
    "content": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.EndpointConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.reporters.MatchResult\nimport de.codecentric.hikaku.reporters.Reporter\nimport kotlin.test.fail\n\n/**\n * Entry point for writing a hikaku test. Provide the [EndpointConverter]s and call [match] to test if the specification and the implementation of your REST-API match.\n * @param specification An [EndpointConverter] which converts your specification for the equality check.\n * @param implementation An [EndpointConverter]  which converts your implementation for the equality check.\n * @param config The configuration is optional. It lets you control the matching.\n */\nclass Hikaku(\n        private val specification: EndpointConverter,\n        private val implementation: EndpointConverter,\n        var config: HikakuConfig = HikakuConfig()\n) {\n    private val supportedFeatures = SupportedFeatures(specification.supportedFeatures.intersect(implementation.supportedFeatures))\n\n    private fun Set<Endpoint>.applyConfig(config: HikakuConfig): List<Endpoint> {\n        val result = this.toMutableList()\n\n        config.filters.forEach {\n            result.removeAll(this.filter(it))\n        }\n\n        return result\n    }\n\n    private fun reportResult(matchResult: MatchResult) {\n        config.reporters.forEach { it.report(matchResult) }\n    }\n\n    /**\n     * Calling this method creates a [MatchResult]. It will be passed to the [Reporter] defined in the configuration and call [assert] with the end result.\n     */\n    fun match() {\n        val specificationEndpoints = specification\n                .conversionResult\n                .applyConfig(config)\n                .toSet()\n\n        val implementationEndpoints = implementation\n                .conversionResult\n                .applyConfig(config)\n                .toSet()\n\n        val notExpected = implementationEndpoints.toMutableSet()\n        val notFound = specificationEndpoints.toMutableSet()\n\n        specificationEndpoints.forEach { currentEndpoint ->\n            if (iterableContains(notExpected, currentEndpoint)) {\n                notExpected.removeIf(endpointMatches(currentEndpoint))\n                notFound.removeIf(endpointMatches(currentEndpoint))\n            }\n        }\n\n        reportResult(\n                MatchResult(\n                        supportedFeatures,\n                        specificationEndpoints,\n                        implementationEndpoints,\n                        notFound,\n                        notExpected\n                )\n        )\n\n        if (notExpected.isNotEmpty() || notFound.isNotEmpty()) {\n            fail(\"Implementation does not match specification.\")\n        }\n    }\n\n    private fun endpointMatches(otherEndpoint: Endpoint): (Endpoint) -> Boolean {\n        return {\n            var matches = true\n            matches = matches && it.path == otherEndpoint.path\n            matches = matches && it.httpMethod == otherEndpoint.httpMethod\n\n            supportedFeatures.forEach { feature ->\n                matches = when (feature) {\n                    Feature.QueryParameters -> matches && it.queryParameters == otherEndpoint.queryParameters\n                    Feature.PathParameters -> matches && it.pathParameters ==  otherEndpoint.pathParameters\n                    Feature.HeaderParameters -> matches && it.headerParameters == otherEndpoint.headerParameters\n                    Feature.MatrixParameters -> matches && it.matrixParameters == otherEndpoint.matrixParameters\n                    Feature.Produces -> matches && it.produces == otherEndpoint.produces\n                    Feature.Consumes -> matches && it.consumes == otherEndpoint.consumes\n                    Feature.Deprecation -> matches && it.deprecated == otherEndpoint.deprecated\n                }\n            }\n\n            matches\n        }\n    }\n\n    private fun iterableContains(notExpected: Set<Endpoint>, value: Endpoint) = notExpected.any(endpointMatches(value))\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/HikakuConfig.kt",
    "content": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.reporters.CommandLineReporter\nimport de.codecentric.hikaku.reporters.MatchResult\nimport de.codecentric.hikaku.reporters.Reporter\n\n/**\n * Configuration for [Hikaku] class. It lets you partially control the matching process.\n * @param reporters The [MatchResult] will be passed to one or many [Reporter] before the test either fails or succeeds. Default is a [CommandLineReporter] that prints the results to [System.out].\n * @param filters Filtering rule: [Endpoint]s matching the predicate will be ignored.\n */\ndata class HikakuConfig\n@JvmOverloads constructor(\n        val reporters: List<Reporter> = listOf(CommandLineReporter()),\n        val filters: List<(Endpoint) -> Boolean> = emptyList()\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/SupportedFeatures.kt",
    "content": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.converters.EndpointConverter\n\n/**\n * A list of features supported by an [EndpointConverter].\n */\nclass SupportedFeatures(\n    private val supportedFeatures: Set<Feature> = emptySet()\n) : Set<SupportedFeatures.Feature> by supportedFeatures {\n\n    constructor(vararg feature: Feature): this(feature.toSet())\n\n    enum class Feature {\n        /** Checks the equality of query parameters. */\n        QueryParameters,\n        /** Checks the equality of path parameters. */\n        PathParameters,\n        /** Checks the equality of header parameters. */\n        HeaderParameters,\n        /** Checks supported media type of responses. */\n        Produces,\n        /** Checks supported media type of requests. */\n        Consumes,\n        /** Checks the equality of matrix parameters. */\n        MatrixParameters,\n        /** Checks the equality of deprecation. */\n        Deprecation\n    }\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/AbstractEndpointConverter.kt",
    "content": "package de.codecentric.hikaku.converters\n\nimport de.codecentric.hikaku.endpoints.Endpoint\n\n/**\n * Abstract [EndpointConverter] which triggers conversion when accessing the [conversionResult]s.\n */\nabstract class AbstractEndpointConverter : EndpointConverter {\n\n    override val conversionResult: Set<Endpoint> by lazy {\n        this.convert()\n    }\n\n    abstract fun convert(): Set<Endpoint>\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/ClassLocator.kt",
    "content": "package de.codecentric.hikaku.converters\n\nimport de.codecentric.hikaku.extensions.extension\nimport de.codecentric.hikaku.extensions.nameWithoutExtension\nimport java.nio.file.Files\nimport java.nio.file.Path\nimport java.nio.file.Paths\n\n/**\n * Original code snippet found at [dzone](https://dzone.com/articles/get-all-classes-within-package) posted by [Victor Tatai](https://dzone.com/users/74061/vtatai.html).\n */\nobject ClassLocator {\n\n    fun getClasses(packageName: String): List<Class<*>> {\n        val classLoader = Thread.currentThread().contextClassLoader\n        val path = packageName.replace('.', '/')\n        val resources = classLoader.getResources(path)\n        val dirs = mutableListOf<Path>()\n\n        resources.iterator().forEach {\n            dirs.add(Paths.get(it.toURI()))\n        }\n\n        val classes = mutableListOf<Class<*>>()\n\n        for (directory in dirs) {\n            classes.addAll(findClasses(directory, packageName))\n        }\n\n        return classes\n    }\n\n    private fun findClasses(directory: Path, packageName: String): List<Class<*>> {\n        val classes = mutableListOf<Class<*>>()\n\n        if (!Files.exists(directory)) {\n            return classes\n        }\n\n        Files.list(directory)\n                .forEach {\n                    if (Files.isDirectory(it)) {\n                        classes.addAll(findClasses(it, \"$packageName.${it.fileName}\"))\n                    } else if (it.extension() == \"class\") {\n                        classes.add(Class.forName(\"$packageName.${it.nameWithoutExtension()}\"))\n                    }\n                }\n\n        return classes\n    }\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/EndpointConverter.kt",
    "content": "package de.codecentric.hikaku.converters\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.endpoints.Endpoint\n\n/**\n * Converts either a specific type of specification or implementation into the internal hikaku format in order to be able to perform a matching on the extracted components.\n */\ninterface EndpointConverter {\n\n    /** Result of the conversion containing all extracted [Endpoint]s. */\n    val conversionResult: Set<Endpoint>\n\n    /** List of [Feature]s that this [EndpointConverter]s supports. */\n    val supportedFeatures: SupportedFeatures\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/EndpointConverterException.kt",
    "content": "package de.codecentric.hikaku.converters\n\n/**\n * Is thrown in case an [EndpointConverter] is not able to perform the conversion.\n */\nclass EndpointConverterException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause) {\n    constructor(throwable: Throwable): this(throwable.message, throwable)\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/Endpoint.kt",
    "content": "package de.codecentric.hikaku.endpoints\n\n/**\n * A single [Endpoint] containing all information. Each [Endpoint] consists of exactly one path in combination with exactly one [HttpMethod].\n * If a REST endpoint supports multiple [HttpMethod]s, this will result in multiple [Endpoint] instances.\n * @param path The path excluding a base path. **Example:** `/todos`\n * @param produces Supported media types for the response.\n * @param consumes Supported media types for the request.\n */\ndata class Endpoint(\n        val path: String,\n        val httpMethod: HttpMethod,\n        val queryParameters: Set<QueryParameter> = emptySet(),\n        val pathParameters: Set<PathParameter> = emptySet(),\n        val headerParameters: Set<HeaderParameter> = emptySet(),\n        val matrixParameters: Set<MatrixParameter> = emptySet(),\n        val produces: Set<String> = emptySet(),\n        val consumes: Set<String> = emptySet(),\n        val deprecated: Boolean = false\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/HeaderParameter.kt",
    "content": "package de.codecentric.hikaku.endpoints\n\ndata class HeaderParameter(\n    val parameterName: String,\n    val required: Boolean = false\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/HttpMethod.kt",
    "content": "package de.codecentric.hikaku.endpoints\n\nenum class HttpMethod {\n    GET,\n    POST,\n    HEAD,\n    PUT,\n    PATCH,\n    DELETE,\n    TRACE,\n    OPTIONS\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/MatrixParameter.kt",
    "content": "package de.codecentric.hikaku.endpoints\n\ndata class MatrixParameter(\n        val parameterName: String,\n        val required: Boolean = false\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/PathParameter.kt",
    "content": "package de.codecentric.hikaku.endpoints\n\ndata class PathParameter(\n        val parameterName: String\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/QueryParameter.kt",
    "content": "package de.codecentric.hikaku.endpoints\n\ndata class QueryParameter(\n        val parameterName: String,\n        val required: Boolean = false\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/extensions/ClassExtensions.kt",
    "content": "package de.codecentric.hikaku.extensions\n\nimport kotlin.reflect.KClass\nimport kotlin.reflect.jvm.jvmName\n\nfun KClass<*>.isUnit(): Boolean {\n    return this.isInstance(Unit) ||\n    this.jvmName == \"java.lang.Void\" ||\n    this.jvmName == \"void\"\n}\n\nfun KClass<*>.isString(): Boolean {\n    return this.isInstance(String) ||\n            this.jvmName == \"java.lang.String\"\n}\n"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/extensions/FileExtensions.kt",
    "content": "package de.codecentric.hikaku.extensions\n\nimport java.io.File\n\nfun File.checkFileValidity(vararg extensions: String) {\n    this.toPath().checkFileValidity(*extensions)\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/extensions/PathExtensions.kt",
    "content": "package de.codecentric.hikaku.extensions\n\nimport java.nio.file.Files\nimport java.nio.file.Path\n\nfun Path.nameWithoutExtension() = fileName.toString().substringBeforeLast(\".\")\n\nfun Path.extension() = fileName.toString().substringAfterLast(\".\")\n\nfun Path.checkFileValidity(vararg extensions: String) {\n    require(Files.exists(this)) { \"Given file does not exist.\" }\n    require(Files.isRegularFile(this)) { \"Given file is not a regular file.\" }\n\n    if (extensions.isNotEmpty()) {\n        extensions.map {it.substringAfter('.') }\n                .filter { this.extension() == it }\n                .ifEmpty { throw IllegalArgumentException(\"Given file is not of type ${extensions.joinToString()}\") }\n    }\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/CommandLineReporter.kt",
    "content": "package de.codecentric.hikaku.reporters\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.*\nimport de.codecentric.hikaku.endpoints.*\n\n/**\n * Simply prints the result to [System.out].\n */\nclass CommandLineReporter : Reporter {\n\n    override fun report(endpointMatchResult: MatchResult) {\n        val heading = \"hikaku test result:\"\n\n        println(\"\\n\")\n        println(heading)\n        println(\"#\".repeat(heading.length))\n\n        val features = endpointMatchResult.supportedFeatures.joinToString(separator = \", \")\n        println(\"The following features were used for matching: HttpMethod, Path, $features\")\n\n\n        if (endpointMatchResult.notFound.isEmpty() && endpointMatchResult.notExpected.isEmpty()) {\n            println (\"\")\n            println (\"✅ Test successful. Specification and implementation match.\")\n        }\n\n\n        if (endpointMatchResult.notFound.isNotEmpty()) {\n            println(\"\\n👀 Expected, but unable to find:\")\n\n            endpointMatchResult.notFound.forEach {\n                printEndpoint(endpointMatchResult.supportedFeatures, it)\n            }\n        }\n\n        if (endpointMatchResult.notExpected.isNotEmpty()) {\n            println(\"\\n👻 Unexpected, but found:\")\n\n            endpointMatchResult.notExpected.forEach {\n                printEndpoint(endpointMatchResult.supportedFeatures, it)\n            }\n        }\n    }\n\n    private fun printEndpoint(supportedFeatures: SupportedFeatures, endpoint: Endpoint) {\n        var path = \"< ${endpoint.httpMethod} ${endpoint.path}\"\n\n        supportedFeatures.forEach {\n            path += when(it) {\n                Feature.QueryParameters -> listQueryParameters(endpoint.queryParameters)\n                Feature.PathParameters -> listPathParameters(endpoint.pathParameters)\n                Feature.HeaderParameters -> listHeaderParameter(endpoint.headerParameters)\n                Feature.MatrixParameters -> listMatrixParameter(endpoint.matrixParameters)\n                Feature.Consumes -> listRequestMediaTypes(endpoint.consumes)\n                Feature.Produces -> listResponseMediaTypes(endpoint.produces)\n                Feature.Deprecation -> if (endpoint.deprecated) \"  Deprecated\" else \"\"\n            }\n        }\n\n        println(\"$path >\")\n    }\n\n    private fun listQueryParameters(queryParameters: Set<QueryParameter>) =\n            \"  QueryParameters[${queryParameters.joinToString {\n                \"${it.parameterName} (${if(it.required) \"required\" else \"optional\"})\"\n            }}]\"\n\n    private fun listPathParameters(pathParameters: Set<PathParameter>) =\n            \"  PathParameters[${pathParameters.joinToString {\n                it.parameterName\n            }}]\"\n\n    private fun listHeaderParameter(headerParameters: Set<HeaderParameter>) =\n            \"  HeaderParameters[${headerParameters.joinToString {\n                \"${it.parameterName} (${if(it.required) \"required\" else \"optional\"})\"\n            }}]\"\n\n    private fun listMatrixParameter(matrixParameters: Set<MatrixParameter>) =\n            \"  MatrixParameters[${matrixParameters.joinToString {\n                \"${it.parameterName} (${if(it.required) \"required\" else \"optional\"})\"\n            }}]\"\n\n    private fun listRequestMediaTypes(requestMediaTypes: Set<String>) =\n            \"  Consumes[${requestMediaTypes.joinToString()}]\"\n\n    private fun listResponseMediaTypes(responseMediaTypes: Set<String>) =\n            \"  Produces[${responseMediaTypes.joinToString()}]\"\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/MatchResult.kt",
    "content": "package de.codecentric.hikaku.reporters\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.endpoints.Endpoint\n\n/**\n * Contains the complete result.\n * @param supportedFeatures Contains all features which have been used for the match.\n * @param specificationEndpoints All [Endpoint]s extracted from the specification.\n * @param implementationEndpoints All [Endpoint]s extracted from the implementation.\n * @param notFound A [Set] of [Endpoint]s which were expected due to their existence in the specification, but which couldn't be found.\n * @param notExpected A [Set] of [Endpoint]s which have been found in the implementation, but which were unexpected, because they don't exist in the specification.\n */\ndata class MatchResult(\n        val supportedFeatures: SupportedFeatures,\n        val specificationEndpoints: Set<Endpoint>,\n        val implementationEndpoints: Set<Endpoint>,\n        val notFound: Set<Endpoint>,\n        val notExpected: Set<Endpoint>\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/NoOperationReporter.kt",
    "content": "package de.codecentric.hikaku.reporters\n\n/**\n * Receives the result and does nothing.\n */\nclass NoOperationReporter : Reporter {\n    override fun report(endpointMatchResult: MatchResult) { }\n}"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/Reporter.kt",
    "content": "package de.codecentric.hikaku.reporters\n\n/**\n * A [Reporter] will receive the [MatchResult] before the test terminates.\n */\ninterface Reporter {\n    fun report(endpointMatchResult: MatchResult)\n}"
  },
  {
    "path": "core/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/HikakuTest.kt",
    "content": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.EndpointConverter\nimport de.codecentric.hikaku.endpoints.*\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport de.codecentric.hikaku.reporters.MatchResult\nimport de.codecentric.hikaku.reporters.NoOperationReporter\nimport de.codecentric.hikaku.reporters.Reporter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.opentest4j.AssertionFailedError\nimport kotlin.test.assertFailsWith\n\nclass HikakuTest {\n\n    @Nested\n    inner class EndpointBasicsTests {\n\n        @Test\n        fun `specification and implementation having different amounts of endpoints in conversion results let the test fail`() {\n            //given\n            val specificationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val implementationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val hikaku = Hikaku(\n                    specificationDummyConverter,\n                    implementationDummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            assertFailsWith<AssertionError> {\n                hikaku.match()\n            }\n        }\n\n        @Test\n        fun `paths in random order match`() {\n            //given\n            val specificationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/c\", GET),\n                        Endpoint(\"/a\", GET),\n                        Endpoint(\"/b\", GET)\n\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val implementationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/b\", GET),\n                        Endpoint(\"/c\", GET),\n                        Endpoint(\"/a\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n            }\n\n            val hikaku = Hikaku(\n                    specificationDummyConverter,\n                    implementationDummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            hikaku.match()\n        }\n\n        @Test\n        fun `same number of Endpoints, but paths don't match`() {\n            //given\n            val specificationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/c\", GET),\n                        Endpoint(\"/a\", GET),\n                        Endpoint(\"/b\", GET)\n\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val implementationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/y\", GET),\n                        Endpoint(\"/z\", GET),\n                        Endpoint(\"/a\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val hikaku = Hikaku(\n                    specificationDummyConverter,\n                    implementationDummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            assertFailsWith<AssertionFailedError> {\n                hikaku.match()\n            }\n        }\n\n        @Test\n        fun `http methods in random order match`() {\n            //given\n            val specificationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", GET)\n\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val implementationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE)\n                )\n                override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n            }\n\n            val hikaku = Hikaku(\n                    specificationDummyConverter,\n                    implementationDummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            hikaku.match()\n        }\n\n        @Test\n        fun `same number of Endpoints, but http methods don't match`() {\n            //given\n            val specificationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", GET)\n\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val implementationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", HEAD)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val hikaku = Hikaku(\n                    specificationDummyConverter,\n                    implementationDummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            assertFailsWith<AssertionFailedError> {\n                hikaku.match()\n            }\n        }\n    }\n\n    @Nested\n    inner class FeatureTests {\n\n        @Nested\n        inner class PathParameterTests {\n\n            @Test\n            fun `path parameter in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{organizationId}/{accountId}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"accountId\"),\n                                            PathParameter(\"organizationId\")\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{organizationId}/{accountId}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"organizationId\"),\n                                            PathParameter(\"accountId\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `path parameter are skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"id\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"othername\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `path parameter don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{accountId}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"accountId\")\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"id\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n\n        @Nested\n        inner class QueryParameterNameTests {\n\n            @Test\n            fun `query parameter names in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\"),\n                                            QueryParameter(\"tag\"),\n                                            QueryParameter(\"query\")\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"query\"),\n                                            QueryParameter(\"filter\"),\n                                            QueryParameter(\"tag\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `query parameter names are skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"tag\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `query parameter names don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"tag\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n\n            @Test\n            fun `query parameter required matches if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\", true)\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\", true)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `query parameter required is skipped if option is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\", true)\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\", false)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `query parameter required don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\", true)\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    queryParameters = setOf(\n                                            QueryParameter(\"filter\", false)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n\n        @Nested\n        inner class HeaderParameterNameTests {\n\n            @Test\n            fun `header parameter names in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"x-b3-traceid\"),\n                                            HeaderParameter(\"allow-cache\")\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\"),\n                                            HeaderParameter(\"x-b3-traceid\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `header parameter names are skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"x-b3-traceid\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `header parameter names don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"cache\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n\n            @Test\n            fun `header parameter required matches if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\", true)\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\", true)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `header parameter required is skipped if option is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\", false)\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\", true)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `header parameter required don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\", true)\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"allow-cache\", false)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n\n        @Nested\n        inner class MatrixParameterNameTests {\n\n            @Test\n            fun `matrix parameter names in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"tag\"),\n                                            MatrixParameter(\"done\")\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"done\"),\n                                            MatrixParameter(\"tag\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `matrix parameter names are skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"done\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"tag\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `matrix parameter names don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"tag\")\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"done\")\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n\n            @Test\n            fun `matrix parameter required matches if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"tag\", true)\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"tag\", true)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `matrix parameter required is skipped if option is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"tag\", true)\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    headerParameters = setOf(\n                                            HeaderParameter(\"tag\", false)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `matrix parameter required don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"allow-cache\", true)\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    matrixParameters = setOf(\n                                            MatrixParameter(\"allow-cache\", false)\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n\n        @Nested\n        inner class ProducesTests {\n\n            @Test\n            fun `media types in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(\n                                            \"application/json\",\n                                            \"text/plain\"\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Produces)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(\n                                            \"text/plain\",\n                                            \"application/json\"\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Produces)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `produces is skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(\n                                            \"application/xml\",\n                                            \"text/plain\"\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(\n                                            \"application/json\"\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Produces)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `media types don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(\n                                            \"application/xml\",\n                                            \"text/plain\"\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Produces)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(\n                                            \"application/json\"\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Produces)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n\n        @Nested\n        inner class ConsumesTests {\n\n            @Test\n            fun `media types in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(\n                                            \"application/json\",\n                                            \"text/plain\"\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(\n                                            \"text/plain\",\n                                            \"application/json\"\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `produces is skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(\n                                            \"application/xml\",\n                                            \"text/plain\"\n                                    )\n                            )\n\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(\n                                            \"application/json\"\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `media types don't match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(\n                                            \"application/xml\",\n                                            \"text/plain\"\n                                    )\n                            )\n\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(\n                                            \"application/json\"\n                                    )\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n\n        @Nested\n        inner class DeprecationTests {\n\n            @Test\n            fun `deprecation info in random order match if the feature is supported by both converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    deprecated = false\n                            ),\n                            Endpoint(\n                                    path = \"/todos/tags\",\n                                    httpMethod = GET,\n                                    deprecated = true\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/tags\",\n                                    httpMethod = GET,\n                                    deprecated = true\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    deprecated = false\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `deprecation info is skipped if the feature is not supported by one of the converters`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    deprecated = false\n                            )\n                    )\n\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    deprecated = true\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                hikaku.match()\n            }\n\n            @Test\n            fun `deprecation info does not match`() {\n                //given\n                val specificationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    deprecated = false\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)\n                }\n\n                val implementationDummyConverter = object : EndpointConverter {\n                    override val conversionResult: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    deprecated = true\n                            )\n                    )\n                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)\n                }\n\n                val hikaku = Hikaku(\n                        specificationDummyConverter,\n                        implementationDummyConverter,\n                        HikakuConfig(\n                                reporters = listOf(NoOperationReporter())\n                        )\n                )\n\n                //when\n                assertFailsWith<AssertionFailedError> {\n                    hikaku.match()\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class ConfigTests {\n\n        @Test\n        fun `ignore endpoints with http method HEAD and OPTIONS on specification`() {\n            //given\n            val dummyConverterWithHeadAndOptions = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val dummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val hikaku = Hikaku(\n                    dummyConverterWithHeadAndOptions,\n                    dummyConverter,\n                    HikakuConfig(\n                            filters = listOf (\n                                { endpoint -> endpoint.httpMethod == HEAD },\n                                { endpoint -> endpoint.httpMethod == OPTIONS }\n                            ),\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            hikaku.match()\n        }\n\n        @Test\n        fun `ignore endpoints with http method HEAD and OPTIONS on implementation`() {\n            //given\n            val dummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val dummyConverterWithHeadAndOptions = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val hikaku = Hikaku(\n                    dummyConverter,\n                    dummyConverterWithHeadAndOptions,\n                    HikakuConfig(\n                            filters = listOf (\n                                    { endpoint -> endpoint.httpMethod == HEAD },\n                                    { endpoint -> endpoint.httpMethod == OPTIONS }\n                            ),\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            hikaku.match()\n        }\n\n        @Test\n        fun `ignore specific paths`() {\n            //given\n            val specificationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val implementationDummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/error\", GET),\n                        Endpoint(\"/error\", HEAD),\n                        Endpoint(\"/error\", OPTIONS),\n                        Endpoint(\"/actuator/health\", OPTIONS)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n            val hikaku = Hikaku(\n                    specificationDummyConverter,\n                    implementationDummyConverter,\n                    HikakuConfig(\n                            filters = listOf (\n                                    { endpoint -> endpoint.path == \"/error\" },\n                                    { endpoint -> endpoint.path.startsWith(\"/actuator\") }\n                            ),\n                            reporters = listOf(NoOperationReporter())\n                    )\n            )\n\n            //when\n            hikaku.match()\n        }\n    }\n\n    @Nested\n    inner class ReporterTests {\n\n        @Test\n        fun `MatchResult has to be passed to the Reporter`() {\n            //given\n            val dummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n\n            val reporter = object : Reporter {\n                var hasBeenCalled: Boolean = false\n\n                override fun report(endpointMatchResult: MatchResult) {\n                    hasBeenCalled = true\n                }\n            }\n\n            val hikaku = Hikaku(\n                    dummyConverter,\n                    dummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(reporter)\n                    )\n            )\n\n            //when\n            hikaku.match()\n\n            //then\n            assertThat(reporter.hasBeenCalled).isTrue()\n        }\n\n        @Test\n        fun `MatchResult can be passed to multiple Reporter`() {\n            //given\n            val dummyConverter = object : EndpointConverter {\n                override val conversionResult: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET)\n                )\n                override val supportedFeatures = SupportedFeatures()\n            }\n\n\n            val firstReporter = object : Reporter {\n                var hasBeenCalled: Boolean = false\n\n                override fun report(endpointMatchResult: MatchResult) {\n                    hasBeenCalled = true\n                }\n            }\n\n            val secondReporter = object : Reporter {\n                var hasBeenCalled: Boolean = false\n\n                override fun report(endpointMatchResult: MatchResult) {\n                    hasBeenCalled = true\n                }\n            }\n\n            val hikaku = Hikaku(\n                    dummyConverter,\n                    dummyConverter,\n                    HikakuConfig(\n                            reporters = listOf(firstReporter, secondReporter)\n                    )\n            )\n\n            //when\n            hikaku.match()\n\n            //then\n            assertThat(firstReporter.hasBeenCalled).isTrue()\n            assertThat(secondReporter.hasBeenCalled).isTrue()\n        }\n    }\n}"
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/extensions/ClassExtensionsTest.kt",
    "content": "package de.codecentric.hikaku.extensions\n\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport java.lang.String as JavaString\n\nclass ClassExtensionsTest {\n\n    @Nested\n    inner class IsUnitTests {\n\n        @Test\n        fun `returns true for kotlin type Unit`() {\n            // given\n            val obj = Unit::class\n\n            // when\n            val result = obj.isUnit()\n\n            // then\n            assertThat(result).isTrue()\n        }\n\n        @Test\n        fun `returns true for java type Void`() {\n            // given\n            val obj = Void::class\n\n            // when\n            val result = obj.isUnit()\n\n            // then\n            assertThat(result).isTrue()\n        }\n\n        @Test\n        fun `returns false for any other type`() {\n            // given\n            val obj = Int::class\n\n            // when\n            val result = obj.isUnit()\n\n            // then\n            assertThat(result).isFalse()\n        }\n    }\n\n    @Nested\n    inner class IsStringTests {\n\n        @Test\n        fun `returns true for kotlin type String`() {\n            // given\n            val obj = String::class\n\n            // when\n            val result = obj.isString()\n\n            // then\n            assertThat(result).isTrue()\n        }\n\n        @Test\n        fun `returns true for java type String`() {\n            // given\n            val obj = JavaString::class\n\n            // when\n            val result = obj.isString()\n\n            // then\n            assertThat(result).isTrue()\n        }\n\n        @Test\n        fun `returns false for any other type`() {\n            // given\n            val obj = Int::class\n\n            // when\n            val result = obj.isString()\n\n            // then\n            assertThat(result).isFalse()\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/extensions/FileExtensionsTest.kt",
    "content": "package de.codecentric.hikaku.extensions\n\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport java.io.File\nimport kotlin.io.path.createTempDirectory\nimport kotlin.test.assertFailsWith\n\nclass FileExtensionsTest {\n\n    @Nested\n    inner class CheckValidityTests {\n\n        @Test\n        fun `non-existing file throws an exception`() {\n            assertFailsWith<IllegalArgumentException> {\n                File(\"test-file-which-does-not-exist.spec\").checkFileValidity()\n            }\n        }\n\n        @Test\n        fun `directory in validity check throws an exception`() {\n            assertFailsWith<IllegalArgumentException> {\n                createTempDirectory().checkFileValidity()\n            }\n        }\n\n        @Test\n        fun `existing file with invalid file extension throws an exception`() {\n            assertFailsWith<IllegalArgumentException> {\n                File(this::class.java.classLoader.getResource(\"test_file.txt\").toURI()).checkFileValidity(\".css\")\n            }\n        }\n\n        @Test\n        fun `file is valid without extension check`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"test_file.txt\").toURI())\n\n            //when\n            file.checkFileValidity()\n\n            //then\n            //no exception is thrown\n        }\n\n        @Test\n        fun `file is valid with extension check`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"test_file.txt\").toURI())\n\n            //when\n            file.checkFileValidity(\".txt\")\n\n            //then\n            //no exception is thrown\n        }\n    }\n}"
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/extensions/PathExtensionsTest.kt",
    "content": "package de.codecentric.hikaku.extensions\n\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Files.createTempDirectory\nimport java.nio.file.Paths\nimport kotlin.test.assertFailsWith\n\nclass PathExtensionsTest {\n\n    @Nested\n    inner class CheckValidityTests {\n\n        @Test\n        fun `non-existing file throws an exception`() {\n            assertFailsWith<IllegalArgumentException> {\n                Paths.get(\"test-file-which-does-not-exist.spec\").checkFileValidity()\n            }\n        }\n\n        @Test\n        fun `directory in validity check throws an exception`() {\n            assertFailsWith<IllegalArgumentException> {\n                createTempDirectory(\"tmp\").checkFileValidity()\n            }\n        }\n\n        @Test\n        fun `existing file with invalid file extension throws an exception`() {\n            assertFailsWith<IllegalArgumentException> {\n                Paths.get(this::class.java.classLoader.getResource(\"test_file.txt\").toURI()).checkFileValidity(\".css\")\n            }\n        }\n\n        @Test\n        fun `file is valid without extension check`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"test_file.txt\").toURI())\n\n            //when\n            file.checkFileValidity()\n\n            //then\n            //no exception is thrown\n        }\n\n        @Test\n        fun `file is valid with extension check`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"test_file.txt\").toURI())\n\n            //when\n            file.checkFileValidity(\".txt\")\n\n            //then\n            //no exception is thrown\n        }\n    }\n}"
  },
  {
    "path": "core/src/test/resources/test_file.txt",
    "content": ""
  },
  {
    "path": "docs/config.md",
    "content": "# hikaku - Config\n\nThe following is a list if configurations.\n\n| config parameter | since | default value | description |\n| --- | --- | --- | --- |\n| filters | 3.0.0 | `emptyList()` | Endpoints matching the predicates in this list will be excluded from matching. |\n| reporters | 1.0.0 | `CommandLineReporter()` | A reporter receives the match results before the assertion is called. Default value is the `CommandLineReporter` which simply prints the results to command line. Another built-in option is the `NoOperationReporter` which does nothing. |"
  },
  {
    "path": "docs/features.md",
    "content": "# hikaku - Features\n\nThe following table gives an overview of all features and which converter supports which feature.\nThe check for endpoint paths and http methods are base functions that every converter has to support. Those are not listed in the table below.\nThere might be various ways to declare or use a feature, so check each converter for unsupported features as well. \n\n| Feature Name | Description | [OpenApi Converter](../openapi/README.md)| [Spring Converter](../spring/README.md) | [WADL Converter](../wadl/README.md) | [RAML Converter](../raml/README.md) | [JAX-RS Converter](../jax-rs/README.md) | [Micronaut Converter](../micronaut/README.md) |\n| --- | --- | --- | --- | --- | --- | --- | --- |\n| QueryParameters | Name of a query parameter and whether the parameter is required or not. _Example:_ `/todos?filter=all`| ✅ _(1.0.0)_ | ✅ _(1.0.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |\n| PathParameters | Name of a path parameter. _Example:_ `/todos/{id}`| ✅ _(1.0.0)_ | ✅ _(1.0.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |\n| HeaderParameters | Name of a header parameter and whether the parameter is required or not. | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |\n| MatrixParameters | Name of a matrix parameter and whether the parameter is required or not. _Example:_ `/todos;param=value` | ❌ | ✅ _(2.1.0)_ | ✅ _(2.1.0)_ | ❌ | ✅ _(2.1.0)_ | ❌ |\n| Produces | Checks the supported media types of the response. | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |\n| Consumes | Checks the supported media types of the request. | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |\n| Deprecation | Checks deprecated endpoints are properly marked. | ✅ _(2.3.0)_ | ✅ _(2.3.0)_ | ❌ | ✅ _(2.3.0)_ | ✅ _(2.3.0)_ | ✅ _(2.3.0)_ |"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.9-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "install-jdk.sh",
    "content": "#!/bin/bash\ninstall_jdk () {\n    if $jabba use $JDK; then\n        echo $JDK was available and Jabba is using it\n    else\n        echo installing $JDK\n        $jabba install \"$JDK\" || exit $?\n        echo setting $JDK as Jabba default\n        $jabba use $JDK || exit $?\n    fi\n}\n\nunix_pre () {\n    curl -sL https://github.com/shyiko/jabba/raw/master/install.sh | bash && . ~/.jabba/jabba.sh\n    unset _JAVA_OPTIONS\n    export jabba=jabba\n}\n\nlinux () {\n    unix_pre\n}\n\nosx () {\n    unix_pre\n    export JAVA_HOME=\"$HOME/.jabba/jdk/$JDK/Contents/Home\"\n}\n\nwindows () {\n    PowerShell -ExecutionPolicy Bypass -Command '[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-Expression (Invoke-WebRequest https://github.com/shyiko/jabba/raw/master/install.ps1 -UseBasicParsing).Content'\n    export jabba=\"$HOME/.jabba/bin/jabba.exe\"\n    # Windows is unable to clean child processes, so no Gradle daemon allowed\n    export GRADLE_OPTS=\"-Dorg.gradle.daemon=false $GRADLE_OPTS\"\n    echo 'export GRADLE_OPTS=\"-Dorg.gradle.daemon=false $GRADLE_OPTS\"' >> ~/.jdk_config\n    # Apparently exported variables are ignored in subseguent phases on Windows. Write in config file\n    echo \"export JAVA_HOME=\\\"${JAVA_HOME}\\\"\" >> ~/.jdk_config\n    echo \"export PATH=\\\"${PATH}\\\"\" >> ~/.jdk_config\n}\n\necho \"running ${TRAVIS_OS_NAME}-specific configuration\"\nexport JAVA_HOME=\"$HOME/.jabba/jdk/$JDK\"\n$TRAVIS_OS_NAME\nexport PATH=\"$JAVA_HOME/bin:$PATH\"\ninstall_jdk\nwhich java\njava -version"
  },
  {
    "path": "jax-rs/README.md",
    "content": "# hikaku - JAX-RS\n\nConverter for JAX-RS. This converter can be used with frameworks that make use of JAX-RS. For instance:\n+ [Apache CXF](http://cxf.apache.org)\n+ [Dropwizard](https://www.dropwizard.io)\n+ [Jersey](https://jersey.github.io)\n+ [Resteasy](https://resteasy.github.io)\n+ [Restlet](https://restlet.com/open-source/documentation/user-guide/2.3/extensions/jaxrs)\n+ [Quarkus](https://quarkus.io)\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md). To check the feature support for this converter.\n\n## Currently not supported\n\n* Parameters defined on fields or setters\n\n## Usage\n\nInstantiate the converter with a package name which will be scanned recursively for controllers.\n\n_Example_: `JaxRsConverter(\"de.codecentric.hikaku\")`"
  },
  {
    "path": "jax-rs/build.gradle",
    "content": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-jax-rs'\n\ndependencies {\n  api project(':core')\n  api 'jakarta.ws.rs:jakarta.ws.rs-api:3.0.0'\n}\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-jax-rs'\n        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for jax-rs implementations.'\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "jax-rs/src/main/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverter.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.AbstractEndpointConverter\nimport de.codecentric.hikaku.converters.ClassLocator\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.endpoints.*\nimport de.codecentric.hikaku.endpoints.HttpMethod\nimport de.codecentric.hikaku.extensions.isUnit\nimport jakarta.ws.rs.*\nimport java.lang.reflect.Method\n\nclass JaxRsConverter(private val packageName: String) : AbstractEndpointConverter() {\n\n    override val supportedFeatures = SupportedFeatures(\n            Feature.QueryParameters,\n            Feature.PathParameters,\n            Feature.HeaderParameters,\n            Feature.MatrixParameters,\n            Feature.Consumes,\n            Feature.Produces,\n            Feature.Deprecation\n    )\n\n    override fun convert(): Set<Endpoint> {\n        if (packageName.isBlank()) {\n            throw EndpointConverterException(\"Package name must not be blank.\")\n        }\n\n        return ClassLocator.getClasses(packageName)\n                .filter { it.getAnnotation(Path::class.java) != null }\n                .flatMap { extractEndpoints(it) }\n                .toSet()\n    }\n\n    private fun extractEndpoints(resource: Class<*>): List<Endpoint> {\n        return resource.methods\n                .filter { isHttpMethodAnnotationPresent(it) }\n                .map { createEndpoint(resource, it) }\n    }\n\n    private fun isHttpMethodAnnotationPresent(method: Method): Boolean {\n        return when {\n            method.isAnnotationPresent(DELETE::class.java) -> true\n            method.isAnnotationPresent(GET::class.java) -> true\n            method.isAnnotationPresent(HEAD::class.java) -> true\n            method.isAnnotationPresent(OPTIONS::class.java) -> true\n            method.isAnnotationPresent(PATCH::class.java) -> true\n            method.isAnnotationPresent(POST::class.java) -> true\n            method.isAnnotationPresent(PUT::class.java) -> true\n            else -> false\n        }\n    }\n\n    private fun createEndpoint(resource: Class<*>, method: Method) = Endpoint(\n            path = extractPath(resource, method),\n            httpMethod = extractHttpMethod(method),\n            pathParameters = extractPathParameters(method),\n            queryParameters = extractQueryParameters(method),\n            headerParameters = extractHeaderParameters(method),\n            matrixParameters = extractMatrixParameters(method),\n            produces = extractProduces(resource, method),\n            consumes = extractConsumes(resource, method),\n            deprecated = isEndpointDeprecated(method)\n    )\n\n    private fun extractPath(resource: Class<*>, method: Method): String {\n        var pathOnClass = resource.getAnnotation(Path::class.java).value\n        val pathOnFunction = if (method.isAnnotationPresent(Path::class.java)) {\n            method.getAnnotation(Path::class.java).value\n        } else {\n            \"\"\n        }\n\n        if (!pathOnClass.startsWith(\"/\")) {\n            pathOnClass = \"/$pathOnClass\"\n        }\n\n        val combinedPath = \"$pathOnClass/$pathOnFunction\".replace(Regex(\"/+\"), \"/\")\n\n        return if (combinedPath.endsWith('/')) {\n            combinedPath.substringBeforeLast('/')\n        } else {\n            combinedPath\n        }\n    }\n\n    private fun extractHttpMethod(method: Method): HttpMethod {\n        return when {\n            method.isAnnotationPresent(DELETE::class.java) -> HttpMethod.DELETE\n            method.isAnnotationPresent(GET::class.java) -> HttpMethod.GET\n            method.isAnnotationPresent(HEAD::class.java) -> HttpMethod.HEAD\n            method.isAnnotationPresent(OPTIONS::class.java) -> HttpMethod.OPTIONS\n            method.isAnnotationPresent(PATCH::class.java) -> HttpMethod.PATCH\n            method.isAnnotationPresent(POST::class.java) -> HttpMethod.POST\n            method.isAnnotationPresent(PUT::class.java) -> HttpMethod.PUT\n            else -> throw IllegalStateException(\"Unable to determine http method. Valid annotation not found.\")\n        }\n    }\n\n    private fun extractProduces(resource: Class<*>, method: Method): Set<String> {\n        val annotationValue = when {\n            method.isAnnotationPresent(Produces::class.java) -> method.getAnnotation(Produces::class.java).value.toSet()\n            resource.isAnnotationPresent(Produces::class.java) -> resource.getAnnotation(Produces::class.java).value.toSet()\n            else -> setOf(\"*/*\")\n        }\n\n        return if (method.returnType.kotlin.isUnit()) {\n            emptySet()\n        } else {\n            annotationValue\n        }\n    }\n\n    private fun extractConsumes(resource: Class<*>, method: Method): Set<String> {\n        val annotationValue = when {\n            method.isAnnotationPresent(Consumes::class.java) -> method.getAnnotation(Consumes::class.java).value.toSet()\n            resource.isAnnotationPresent(Consumes::class.java) -> resource.getAnnotation(Consumes::class.java).value.toSet()\n            else -> setOf(\"*/*\")\n        }\n\n        return if (containsRequestBody(method)) {\n            annotationValue\n        } else {\n            emptySet()\n        }\n    }\n\n    private fun containsRequestBody(method: Method): Boolean {\n        return method.parameters\n                .filterNot { it.isAnnotationPresent(BeanParam::class.java) }\n                .filterNot { it.isAnnotationPresent(CookieParam::class.java) }\n                .filterNot { it.isAnnotationPresent(DefaultValue::class.java) }\n                .filterNot { it.isAnnotationPresent(Encoded::class.java) }\n                .filterNot { it.isAnnotationPresent(FormParam::class.java) }\n                .filterNot { it.isAnnotationPresent(HeaderParam::class.java) }\n                .filterNot { it.isAnnotationPresent(MatrixParam::class.java) }\n                .filterNot { it.isAnnotationPresent(PathParam::class.java) }\n                .filterNot { it.isAnnotationPresent(QueryParam::class.java) }\n                .isNotEmpty()\n    }\n\n    private fun extractQueryParameters(method: Method): Set<QueryParameter> {\n        return method.parameters\n                .filter { it.isAnnotationPresent(QueryParam::class.java) }\n                .map { it.getAnnotation(QueryParam::class.java) }\n                .map { (it as QueryParam).value }\n                .map { QueryParameter(it, false) }\n                .toSet()\n    }\n\n    private fun extractPathParameters(method: Method): Set<PathParameter> {\n        return method.parameters\n                .filter { it.isAnnotationPresent(PathParam::class.java) }\n                .map { it.getAnnotation(PathParam::class.java) }\n                .map { (it as PathParam).value }\n                .map { PathParameter(it) }\n                .toSet()\n    }\n\n    private fun extractHeaderParameters(method: Method): Set<HeaderParameter> {\n        return method.parameters\n                .filter { it.isAnnotationPresent(HeaderParam::class.java) }\n                .map { it.getAnnotation(HeaderParam::class.java) }\n                .map { (it as HeaderParam).value }\n                .map { HeaderParameter(it) }\n                .toSet()\n    }\n\n    private fun extractMatrixParameters(method: Method): Set<MatrixParameter> {\n        return method.parameters\n                .filter { it.isAnnotationPresent(MatrixParam::class.java) }\n                .map { it.getAnnotation(MatrixParam::class.java) }\n                .map { (it as MatrixParam).value }\n                .map { MatrixParameter(it) }\n                .toSet()\n    }\n\n    private fun isEndpointDeprecated(method: Method) =\n            method.isAnnotationPresent(Deprecated::class.java)\n                    || method.declaringClass.isAnnotationPresent(Deprecated::class.java)\n}\n"
  },
  {
    "path": "jax-rs/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterConsumesTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterConsumesTest {\n\n    @Test\n    fun `single media type defined on class`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.singlemediatypeonclass\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `single media type defined on function`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.singlemediatypeonfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `single media type without request body`() {\n        // given\n        val specification = setOf(\n                Endpoint( \"/todos\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.singlemediatypewithoutrequestbody\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `request body, but no annotation`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"*/*\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.noannotation\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `no request body, but other annotated parameter`() {\n        // given\n        val specification = setOf(\n                Endpoint(\"/todos\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.singlemediatypewithoutrequestbodybutotherannotatedparameter\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple media type defined on class`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.multiplemediatypesonclass\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple media type defined on function`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.multiplemediatypesonfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `function declaration overwrites class declaration`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.consumes.functiondeclarationoverwritesclassdeclaration\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterDeprecationTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterDeprecationTest {\n\n    @Test\n    fun `no deprecation`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        deprecated =  false\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.deprecation.none\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `deprecated class`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        deprecated =  true\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.deprecation.onclass\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `deprecated function`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        deprecated = true\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.deprecation.onfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterHeaderParametersTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterHeaderParameterTest {\n\n    @Test\n    fun `header parameter on function`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                                HeaderParameter(\"allow-cache\")\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.headerparameters.onfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterHttpMethodsTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterHttpMethodsTest {\n\n    @Test\n    fun `extract all available http methods`() {\n        //given\n        val specification = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/todos\", DELETE),\n                Endpoint(\"/todos\", POST),\n                Endpoint(\"/todos\", PUT),\n                Endpoint(\"/todos\", PATCH),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\"/todos\", HEAD)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.httpmethod.allmethods\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `resource class without http method annotation`() {\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.httpmethod.noannotation\").conversionResult\n\n        //then\n        assertThat(result).isEmpty()\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterMatrixParametersTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.MatrixParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterMatrixParametersTest {\n\n    @Test\n    fun `matrix parameter on function`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        matrixParameters = setOf(\n                                MatrixParameter(\"tag\")\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.matrixparameters.onfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPackageDefinitionTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport org.junit.jupiter.api.Test\nimport kotlin.test.assertFailsWith\n\nclass JaxRsConverterPackageDefinitionTest {\n\n    @Test\n    fun `invoking converter with empty string leads to EndpointConverterException`() {\n        assertFailsWith<EndpointConverterException> {\n            JaxRsConverter(\"\").conversionResult\n        }\n    }\n\n    @Test\n    fun `invoking converter with blank string leads to EndpointConverterException`() {\n        assertFailsWith<EndpointConverterException> {\n            JaxRsConverter(\"     \").conversionResult\n        }\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPathParametersTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterPathParametersTest {\n\n    @Test\n    fun `no path parameter`() {\n        //given\n        val specification = setOf(\n                Endpoint(\"/todos/{id}\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.pathparameters.nopathparameter\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `path parameter on function`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos/{id}\",\n                        httpMethod = GET,\n                        pathParameters = setOf(\n                                PathParameter(\"id\")\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.pathparameters.onfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPathTests.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterPathTests {\n\n    @Test\n    fun `simple path`() {\n        // given\n        val specification = setOf(\n                Endpoint(\"/todos\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.path.simplepath\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `simple path without leading slash`() {\n        // given\n        val specification = setOf(\n                Endpoint(\"/todos\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.path.simplepathwithoutleadingslash\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `nested path`() {\n        // given\n        val specification = setOf(\n                Endpoint(\"/todo/list\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.path.nestedpath\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `nested path without leading slash`() {\n        // given\n        val specification = setOf(\n                Endpoint(\"/todo/list\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.path.nestedpathwithoutleadingslash\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `resource class is not detected, if there is no Path annotation on class level`() {\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.path.nopathonclass\").conversionResult\n\n        //then\n        assertThat(result).isEmpty()\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterProducesTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterProducesTest {\n\n    @Test\n    fun `single media type defined on class`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.singlemediatypeonclass\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `single media type defined on function`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.singlemediatypeonfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `single media type without return type`() {\n        // given\n        val specification = setOf(\n                Endpoint( \"/todos\", GET)\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.singlemediatypewithoutreturntype\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `return type, but no annotation`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"*/*\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.noannotation\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple media type defined on class`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.multiplemediatypesonclass\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple media type defined on function`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.multiplemediatypesonfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `function declaration overwrites class declaration`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.produces.functiondeclarationoverwritesclassdeclaration\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterQueryParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass JaxRsConverterQueryParameterTest {\n\n    @Test\n    fun `query parameter on function`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                                QueryParameter(\"filter\")\n                        )\n                )\n        )\n\n        //when\n        val result = JaxRsConverter(\"test.jaxrs.queryparameters.onfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/functiondeclarationoverwritesclassdeclaration/FunctionDeclarationOverwritesClassDeclaration.kt",
    "content": "package test.jaxrs.consumes.functiondeclarationoverwritesclassdeclaration\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Consumes(\"application/xml\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass FunctionDeclarationOverwritesClassDeclaration {\n\n    @GET\n    @Consumes(\"application/json\", \"text/plain\")\n    fun todo(todo: Todo) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/multiplemediatypesonclass/MultipleMediaTypesOnClass.kt",
    "content": "package test.jaxrs.consumes.multiplemediatypesonclass\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Consumes(\"application/json\", \"application/xml\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass MultipleMediaTypesOnClass {\n\n    @GET\n    fun todo(todo: Todo) {}\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/multiplemediatypesonfunction/MultipleMediaTypesOnFunction.kt",
    "content": "package test.jaxrs.consumes.multiplemediatypesonfunction\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass MultipleMediaTypesOnFunction {\n\n    @GET\n    @Consumes(\"application/json\", \"application/xml\")\n    fun todo(todo: Todo) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/noannotation/NoAnnotation.kt",
    "content": "package test.jaxrs.consumes.noannotation\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass NoAnnotation {\n\n    @GET\n    fun todo(todo: Todo) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypeonclass/ProducesOnClass.kt",
    "content": "package test.jaxrs.consumes.singlemediatypeonclass\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Consumes(\"application/json\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass ProducesOnClass {\n\n    @GET\n    fun todo(todo: Todo) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypeonfunction/ProducesOnFunction.kt",
    "content": "package test.jaxrs.consumes.singlemediatypeonfunction\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass ProducesOnFunction {\n\n    @GET\n    @Consumes(\"application/json\")\n    fun todo(todo: Todo) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypewithoutrequestbody/SingleMediaTypeWithoutRequestBody.kt",
    "content": "package test.jaxrs.consumes.singlemediatypewithoutrequestbody\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass SingleMediaTypeWithoutRequestBody {\n\n    @GET\n    @Consumes(\"application/json\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypewithoutrequestbodybutotherannotatedparameter/SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter.kt",
    "content": "package test.jaxrs.consumes.singlemediatypewithoutrequestbodybutotherannotatedparameter\n\nimport jakarta.ws.rs.*\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter {\n\n    @GET\n    @Consumes(\"application/json\")\n    fun todo(@Encoded filter: String) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/deprecation/none/NoDeprecation.kt",
    "content": "package test.jaxrs.deprecation.none\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass NoDeprecation {\n\n    @GET\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/deprecation/onclass/DeprecationOnClass.kt",
    "content": "package test.jaxrs.deprecation.onclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\n@Deprecated(\"Test\")\nclass DeprecationOnClass {\n\n    @GET\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/deprecation/onfunction/DeprecationOnFunction.kt",
    "content": "package test.jaxrs.deprecation.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass DeprecationOnFunction {\n\n    @GET\n    @Deprecated(\"Test\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/headerparameters/onfunction/HeaderParametersOnFunction.kt",
    "content": "package test.jaxrs.headerparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.HeaderParam\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass HeaderParameterOnFunction {\n\n    @GET\n    fun todo(@HeaderParam(\"allow-cache\") allowCache: String) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/httpmethod/allmethods/AllHttpMethods.kt",
    "content": "package test.jaxrs.httpmethod.allmethods\n\nimport jakarta.ws.rs.*\n\n@Path(\"/todos\")\nclass AllHttpMethods {\n\n    @GET\n    fun getTodo() { }\n\n    @DELETE\n    fun deleteTodo() { }\n\n    @POST\n    fun postTodo() { }\n\n    @PUT\n    fun putTodos() { }\n\n    @PATCH\n    fun patchTodos() { }\n\n    @OPTIONS\n    fun optionsTodos() { }\n\n    @HEAD\n    fun headTodos() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/httpmethod/noannotation/NoAnnotation.kt",
    "content": "package test.jaxrs.httpmethod.noannotation\n\nimport jakarta.ws.rs.Path\n\n@Path(\"\")\nclass NoAnnotation\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/matrixparameters/onfunction/MatrixParametersOnFunction.kt",
    "content": "package test.jaxrs.matrixparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.MatrixParam\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass MatrixParameterOnFunction {\n\n    @GET\n    fun todo(@MatrixParam(\"tag\") tag: String) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/nestedpath/NestedPath.kt",
    "content": "package test.jaxrs.path.nestedpath\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todo\")\nclass NestedPath {\n\n    @GET\n    @Path(\"/list\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/nestedpathwithoutleadingslash/NestedPathWithoutLeadingSlash.kt",
    "content": "package test.jaxrs.path.nestedpathwithoutleadingslash\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todo\")\nclass NestedPath {\n\n    @GET\n    @Path(\"list\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/nopathonclass/NoPathAnnotationOnclass.kt",
    "content": "package test.jaxrs.path.nopathonclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\nclass NoPathAnnotationOnclass {\n\n    @GET\n    @Path(\"/todos\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/simplepath/SimplePath.kt",
    "content": "package test.jaxrs.path.simplepath\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass SimplePath {\n\n    @GET\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/simplepathwithoutleadingslash/SimplePathWithoutLeadingSlash.kt",
    "content": "package test.jaxrs.path.simplepathwithoutleadingslash\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"todos\")\nclass SimplePathWithoutLeadingSlash {\n\n    @GET\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/pathparameters/nopathparameter/NoPathParameter.kt",
    "content": "package test.jaxrs.pathparameters.nopathparameter\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass NoPathParameter {\n\n    @GET\n    @Path(\"/{id}\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/pathparameters/onfunction/PathParameterOnFunction.kt",
    "content": "package test.jaxrs.pathparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.PathParam\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass PathParameterOnFunction {\n\n    @GET\n    @Path(\"/{id}\")\n    fun todo(@PathParam(\"id\") id: String) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/functiondeclarationoverwritesclassdeclaration/FunctionDeclarationOverwritesClassDeclaration.kt",
    "content": "package test.jaxrs.produces.functiondeclarationoverwritesclassdeclaration\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Produces\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Produces(\"application/xml\")\nclass FunctionDeclarationOverwritesClassDeclaration {\n\n    @GET\n    @Produces(\"application/json\", \"text/plain\")\n    fun todo() = Todo()\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/multiplemediatypesonclass/MultipleMediaTypesOnClass.kt",
    "content": "package test.jaxrs.produces.multiplemediatypesonclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Produces\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Produces(\"application/json\", \"application/xml\")\nclass MultipleMediaTypesOnClass {\n\n    @GET\n    fun todo() = Todo()\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/multiplemediatypesonfunction/MultipleMediaTypesOnFunction.kt",
    "content": "package test.jaxrs.produces.multiplemediatypesonfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Produces\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\nclass MultipleMediaTypesOnFunction {\n\n    @GET\n    @Produces(\"application/json\", \"application/xml\")\n    fun todo() = Todo()\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/noannotation/NoAnnotation.kt",
    "content": "package test.jaxrs.produces.noannotation\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\nclass NoAnnotation {\n\n    @GET\n    fun todo() = Todo()\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypeonclass/ProducesOnClass.kt",
    "content": "package test.jaxrs.produces.singlemediatypeonclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Produces\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\n@Produces(\"application/json\")\nclass ProducesOnClass {\n\n    @GET\n    fun todo() = Todo()\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypeonfunction/ProducesOnFunction.kt",
    "content": "package test.jaxrs.produces.singlemediatypeonfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Produces\n\ndata class Todo(val description: String = \"\")\n\n@Path(\"/todos\")\nclass ProducesOnFunction {\n\n    @GET\n    @Produces(\"application/json\")\n    fun todo() = Todo()\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypewithoutreturntype/SingleMediaTypeWithoutReturnType.kt",
    "content": "package test.jaxrs.produces.singlemediatypewithoutreturntype\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Produces\n\n@Path(\"/todos\")\nclass SingleMediaTypeWithoutReturnType {\n\n    @GET\n    @Produces(\"application/json\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/queryparameters/onfunction/QueryParameterOnFunction.kt",
    "content": "package test.jaxrs.queryparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.QueryParam\n\n@Path(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass QueryParameterOnFunction {\n\n    @GET\n    fun todo(@QueryParam(\"filter\") filter: String) { }\n}\n"
  },
  {
    "path": "jax-rs/src/test/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "micronaut/README.md",
    "content": "# hikaku - Micronaut\n\nConverter for Micronaut.\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md). To check the feature support for this converter.\n\n### Paths\n\n+ Supports Controller annotation combined with empty HttpMethod annotation\n  + _Example:_\n```\n@Controller(\"/todos\")\nclass TodosController {\n\n    @Get\n    fun todos() { }\n}\n```\n\n+ Supports Controller annotation combined with HttpMethod annotation\n  + _Example:_\n```\n@Controller(\"/todo\")\nclass TodosController {\n\n    @Get(\"/list\")\n    fun todos() { }\n}\n```\n\n+ Supports alias `uri` for HttpMethod annotation\n  + _Example:_ `@Get(uri = \"/todos\")`\n  \n+ Supports paths with leading and non-leading slash on both Controller and HttpMethod annotation\n  + _Examples:_\n    + `@Controller(\"/todos\")` and `@Controller(\"todos\")`\n    + `@Get(\"/todos\")` and `@Get(\"todos\")`\n\n### Path parameters\n\n+ Supports path parameter without annotation\n  + _Examples:_\n```\n@Controller(\"/todos/{id}\")\nclass TodosController {\n\n    @Get\n    fun todos(id: String) { }\n}\n```\n\n+ Supports path parameter with annotation\n  + _Examples:_\n```\n@Controller(\"/todos/{id}\")\nclass TodosController {\n\n    @Get\n    fun todos(@PathVariable(\"id\") otherName: String) { }\n}\n```\n\n+ Supports using alias `name`\n  + _Examples:_ `@PathVariable(name = \"id\") otherName: String`\n\n### Query parameters\n\n+ Supports query parameter without annotation\n  + _Examples:_\n```\n@Controller(\"/todos\")\nclass TodosController {\n\n    @Get\n    fun todos(filter: String) { }\n}\n```\n\n+ Supports query parameter with annotation\n  + _Examples:_\n```\n@Controller(\"/todos\")\nclass TodosController {\n\n    @Get\n    fun todos(@QueryValue(\"filter\") filter: String) { }\n}\n```\n\n+ Supports setting the parameter _required_ or _optional_ based on the existence of a default value\n  + _Examples:_ `@QueryValue(\"filter\", defaultValue = \"all\") filter: String`\n\n### Header parameters\n\n+ Supports required header parameter\n  + _Examples:_\n```\n@Controller(\"/todos\")\nclass TodosController {\n\n    @Get\n    fun todos(@Header(\"allow-cache\") otherName: String) { }\n}\n```\n\n+ Supports optional header parameter based on the existence of a default value\n  + _Examples:_ `@Header(\"allow-cache\", defaultValue = \"true\") otherName: String`\n  \n### Consumes\n\n+ Supports default media type `application/json`\n\n+ Supports single and multiple media type declarations in Controller annotation\n\n+ Supports Consumes annotation with single and multiple media type declarations on class and function\n\n+ Supports Consumes annotation overriding the value of the Controller annotation\n\n### Produces\n\n+ Supports default media type `application/json`\n\n+ Supports single and multiple media type declarations in Controller annotation\n\n+ Supports Produces annotation with single and multiple media type declarations on class and function\n\n+ Supports Produces annotation overriding the value of the Controller annotation\n\n## Usage\n\nInstantiate the converter with a package name which will be scanned recursively for controllers.\n\n_Example_: `MicronautConverter(\"de.codecentric.hikaku\")`"
  },
  {
    "path": "micronaut/build.gradle",
    "content": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-micronaut'\n\ndependencies {\n  api project(':core')\n  api 'io.micronaut:micronaut-http:3.0.0'\n}\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-micronaut'\n        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for micronaut implementations.'\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "micronaut/src/main/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverter.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.AbstractEndpointConverter\nimport de.codecentric.hikaku.converters.ClassLocator\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.endpoints.*\nimport de.codecentric.hikaku.extensions.isUnit\nimport io.micronaut.http.annotation.*\nimport java.lang.reflect.Method\nimport kotlin.reflect.full.findAnnotation\nimport kotlin.reflect.jvm.kotlinFunction\n\nclass MicronautConverter(private val packageName: String) : AbstractEndpointConverter() {\n\n    override val supportedFeatures = SupportedFeatures(\n        Feature.QueryParameters,\n        Feature.PathParameters,\n        Feature.HeaderParameters,\n        Feature.Produces,\n        Feature.Consumes,\n        Feature.Deprecation\n    )\n\n    override fun convert(): Set<Endpoint> {\n        if (packageName.isBlank()) {\n            throw EndpointConverterException(\"Package name must not be blank.\")\n        }\n\n        return ClassLocator.getClasses(packageName)\n                .filter { it.getAnnotation(Controller::class.java) != null }\n                .flatMap { extractEndpoints(it) }\n                .toSet()\n    }\n\n    private fun extractEndpoints(resource: Class<*>): List<Endpoint> {\n        return resource.methods\n                .filter { isHttpMethodAnnotationPresent(it) }\n                .map { createEndpoint(resource, it) }\n    }\n\n    private fun isHttpMethodAnnotationPresent(method: Method): Boolean {\n        return when {\n            method.isAnnotationPresent(Delete::class.java) -> true\n            method.isAnnotationPresent(Get::class.java) -> true\n            method.isAnnotationPresent(Head::class.java) -> true\n            method.isAnnotationPresent(Options::class.java) -> true\n            method.isAnnotationPresent(Patch::class.java) -> true\n            method.isAnnotationPresent(Post::class.java) -> true\n            method.isAnnotationPresent(Put::class.java) -> true\n            else -> false\n        }\n    }\n\n    private fun createEndpoint(resource: Class<*>, method: Method): Endpoint {\n        val path = extractPath(resource, method)\n\n        return Endpoint(\n                path = path,\n                httpMethod = extractHttpMethod(method),\n                queryParameters = extractQueryParameters(path, method),\n                pathParameters = extractPathParameters(path, method),\n                headerParameters = extractHeaderParameters(method),\n                consumes = extractConsumes(resource, method),\n                produces = extractProduces(resource, method),\n                deprecated = isEndpointDeprecated(method)\n        )\n    }\n\n    private fun extractProduces(resource: Class<*>, method: Method): Set<String> {\n        val methodHasNoReturnType = method.returnType.kotlin.isUnit()\n\n        if (methodHasNoReturnType) {\n            return emptySet()\n        }\n\n        val mediaTypesOnFunction = method.kotlinFunction\n                ?.annotations\n                ?.filterIsInstance<Produces>()\n                ?.flatMap { it.value.map { entry -> entry } }\n                ?.toSet()\n                .orEmpty()\n\n        if (mediaTypesOnFunction.isNotEmpty()) {\n            return mediaTypesOnFunction\n        }\n\n        val mediaTypesOnControllerByConsumesAnnotation = resource.getAnnotation(Produces::class.java)\n                ?.value\n                ?.toSet()\n                .orEmpty()\n\n        if (mediaTypesOnControllerByConsumesAnnotation.isNotEmpty()) {\n            return mediaTypesOnControllerByConsumesAnnotation\n        }\n\n        val mediaTypesDefinedByControllerAnnotation = resource.getAnnotation(Controller::class.java)\n                .produces\n                .toSet()\n\n        if (mediaTypesDefinedByControllerAnnotation.isNotEmpty()) {\n            return mediaTypesDefinedByControllerAnnotation\n        }\n\n        return setOf(\"application/json\")\n    }\n\n    private fun extractConsumes(resource: Class<*>, method: Method): Set<String> {\n        val methodAwaitsPayload = method.kotlinFunction\n                ?.parameters\n                ?.any { it.findAnnotation<Body>() != null }\n                ?: false\n\n        if (!methodAwaitsPayload) {\n            return emptySet()\n        }\n\n        val mediaTypesOnFunction = method.kotlinFunction\n                ?.annotations\n                ?.filterIsInstance<Consumes>()\n                ?.flatMap { it.value.map { entry -> entry } }\n                ?.toSet()\n                .orEmpty()\n\n        if (mediaTypesOnFunction.isNotEmpty()) {\n            return mediaTypesOnFunction\n        }\n\n        val mediaTypesOnControllerByConsumesAnnotation = resource.getAnnotation(Consumes::class.java)\n                ?.value\n                ?.toSet()\n                .orEmpty()\n\n        if (mediaTypesOnControllerByConsumesAnnotation.isNotEmpty()) {\n            return mediaTypesOnControllerByConsumesAnnotation\n        }\n\n        val mediaTypesDefinedByControllerAnnotation = resource.getAnnotation(Controller::class.java)\n                .consumes\n                .toSet()\n\n        if (mediaTypesDefinedByControllerAnnotation.isNotEmpty()) {\n            return mediaTypesDefinedByControllerAnnotation\n        }\n\n        return setOf(\"application/json\")\n    }\n\n    private fun extractPath(resource: Class<*>, method: Method): String {\n        var pathOnClass = resource.getAnnotation(Controller::class.java).value\n        val pathOnFunction = when {\n            method.isAnnotationPresent(Delete::class.java) -> method.getAnnotation(Delete::class.java).value\n            method.isAnnotationPresent(Get::class.java) -> method.getAnnotation(Get::class.java).value\n            method.isAnnotationPresent(Head::class.java) -> method.getAnnotation(Head::class.java).value\n            method.isAnnotationPresent(Options::class.java) -> method.getAnnotation(Options::class.java).value\n            method.isAnnotationPresent(Patch::class.java) -> method.getAnnotation(Patch::class.java).value\n            method.isAnnotationPresent(Post::class.java) -> method.getAnnotation(Post::class.java).value\n            method.isAnnotationPresent(Put::class.java) -> method.getAnnotation(Put::class.java).value\n            else -> \"\"\n        }\n\n        if (!pathOnClass.startsWith(\"/\")) {\n            pathOnClass = \"/$pathOnClass\"\n        }\n\n        val combinedPath = \"$pathOnClass/$pathOnFunction\".replace(Regex(\"/+\"), \"/\")\n\n        return if (combinedPath.endsWith('/')) {\n            combinedPath.substringBeforeLast('/')\n        } else {\n            combinedPath\n        }\n    }\n\n    private fun extractHttpMethod(method: Method): HttpMethod {\n        return when {\n            method.isAnnotationPresent(Delete::class.java) -> HttpMethod.DELETE\n            method.isAnnotationPresent(Get::class.java) -> HttpMethod.GET\n            method.isAnnotationPresent(Head::class.java) -> HttpMethod.HEAD\n            method.isAnnotationPresent(Options::class.java) -> HttpMethod.OPTIONS\n            method.isAnnotationPresent(Patch::class.java) -> HttpMethod.PATCH\n            method.isAnnotationPresent(Post::class.java) -> HttpMethod.POST\n            method.isAnnotationPresent(Put::class.java) -> HttpMethod.PUT\n            else -> throw IllegalStateException(\"Unable to determine http method. Valid annotation not found.\")\n        }\n    }\n\n    private fun extractQueryParameters(path: String, method: Method): Set<QueryParameter> {\n        val queryParameters = method.parameters\n                .filter { it.isAnnotationPresent(QueryValue::class.java) }\n                .map { it.getAnnotation(QueryValue::class.java) }\n                .map { it as QueryValue }\n                .map { QueryParameter(it.value, it.defaultValue.isBlank()) }\n                .toMutableSet()\n\n\n        val queryParameterWithoutAnnotation = methodParametersWithoutAnnotation(method).filterNot { templatesInPath(path).contains(it) }\n                .filterNotNull()\n                .map { QueryParameter(it, false) }\n                .toSet()\n\n        queryParameters.addAll(queryParameterWithoutAnnotation)\n\n        return queryParameters\n    }\n\n    private fun extractPathParameters(path: String, method: Method): Set<PathParameter> {\n        val parameters = method.parameters\n                .filter { it.isAnnotationPresent(PathVariable::class.java) }\n                .map { it.getAnnotation(PathVariable::class.java) as PathVariable }\n                .map {\n                    val pathParameter = if (it.value.isNotBlank()) {\n                        it.value\n                    } else {\n                        it.name\n                    }\n\n                    PathParameter(pathParameter)\n                }\n                .toMutableSet()\n\n        val pathParametersWithoutAnnotation = templatesInPath(path)\n                .filter { methodParametersWithoutAnnotation(method).contains(it) }\n                .map { PathParameter(it) }\n                .toSet()\n\n        parameters.addAll(pathParametersWithoutAnnotation)\n\n        return parameters\n    }\n\n    private fun methodParametersWithoutAnnotation(method: Method) = method.kotlinFunction\n        ?.parameters\n        ?.filter { it.annotations.isEmpty() }\n        ?.map { it.name }\n        .orEmpty()\n\n    private fun templatesInPath(path: String) = Regex(\"\\\\{.+\\\\}\").findAll(path)\n        .map { it.value }\n        .map { it.removePrefix(\"{\") }\n        .map { it.removeSuffix(\"}\") }\n        .toSet()\n\n    private fun extractHeaderParameters(method: Method): Set<HeaderParameter> {\n        return method.parameters\n                .filter { it.isAnnotationPresent(Header::class.java) }\n                .map { it.getAnnotation(Header::class.java) }\n                .map { it as Header }\n                .map { HeaderParameter(it.value, it.defaultValue.isBlank()) }\n                .toSet()\n    }\n\n    private fun isEndpointDeprecated(method: Method) =\n            method.isAnnotationPresent(Deprecated::class.java)\n                    || method.declaringClass.isAnnotationPresent(Deprecated::class.java)\n}\n"
  },
  {
    "path": "micronaut/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterConsumesTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.POST\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterConsumesTest {\n\n    @Nested\n    inner class DeclaredByControllerOnClass {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                \"text/plain\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onclass.onlycontroller.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"text/plain\",\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onclass.onlycontroller.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class ConsumesOnClassOverridesController {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onclass.consumesoverridescontroller.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"application/json\",\n                                    \"application/pdf\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onclass.consumesoverridescontroller.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class DeclaredByConsumesOnFunction {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"text/plain\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onfunction.onlyconsumes.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"text/plain\",\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onfunction.onlyconsumes.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class ConsumesOnFunctionOverridesController {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onfunction.consumesoverridescontroller.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = POST,\n                            consumes = setOf(\n                                    \"application/json\",\n                                    \"application/pdf\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.consumes.onfunction.consumesoverridescontroller.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Test\n    fun `use default media if no consume info has been set`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = POST,\n                        consumes = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.consumes.default\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterDeprecationTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterDeprecationTest {\n\n    @Test\n    fun `no deprecation`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        deprecated =  false\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.deprecation.none\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `deprecated class`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        deprecated =  true\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.deprecation.onclass\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `deprecated function`() {\n        // given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        deprecated = true\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.deprecation.onfunction\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterHeaderParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterHeaderParameterTest {\n\n    @Test\n    fun `optional header parameter`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                                HeaderParameter(\"allow-cache\", false)\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.headerparameters.optional\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `required header parameter`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                                HeaderParameter(\"allow-cache\", true)\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.headerparameters.required\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterPackageDefinitionTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport org.junit.jupiter.api.Test\nimport kotlin.test.assertFailsWith\n\nclass MicronautConverterPackageDefinitionTest {\n\n    @Test\n    fun `invoking converter with empty string leads to EndpointConverterException`() {\n        assertFailsWith<EndpointConverterException> {\n            MicronautConverter(\"\").conversionResult\n        }\n    }\n\n    @Test\n    fun `invoking converter with blank string leads to EndpointConverterException`() {\n        assertFailsWith<EndpointConverterException> {\n            MicronautConverter(\"     \").conversionResult\n        }\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterPathParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterPathParameterTest {\n\n    @Test\n    fun `path parameter defined by variable name`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos/{id}\",\n                        httpMethod = GET,\n                        pathParameters = setOf(\n                                PathParameter(\"id\")\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.pathparameters.variable\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `path parameter defined by annotation using 'value'`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos/{id}\",\n                        httpMethod = GET,\n                        pathParameters = setOf(\n                                PathParameter(\"id\")\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.pathparameters.annotation.value\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `path parameter defined by annotation using 'name'`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos/{id}\",\n                        httpMethod = GET,\n                        pathParameters = setOf(\n                                PathParameter(\"id\")\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.pathparameters.annotation.name\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterPathTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterPathTest {\n\n    @Nested\n    inner class PathOnlyOnControllerTests {\n\n        @Test\n        fun `controller annotation with DELETE annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", DELETE)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.delete\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with GET annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", GET)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.get\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with HEAD annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", HEAD)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.head\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with OPTIONS annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", OPTIONS)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.options\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with PATCH annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", PATCH)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.patch\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with POST annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", POST)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.post\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with PUT annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todos\", PUT)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.onlycontrollerannotation.put\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class PathInBothControllerAndHttpMethodAnnotationTests {\n\n        @Test\n        fun `controller annotation with DELETE annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", DELETE)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.delete\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with GET annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", GET)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.get\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with HEAD annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", HEAD)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.head\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with OPTIONS annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", OPTIONS)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.options\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with PATCH annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", PATCH)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.patch\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with POST annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", POST)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.post\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `controller annotation with PUT annotation`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\"/todo/list\", PUT)\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.path.combinedcontrollerandhttpmethodannotation.put\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Test\n    fun `method does not provide any http method annotation`() {\n        //when\n        val result = MicronautConverter(\"test.micronaut.path.nohttpmethodannotation\").conversionResult\n\n        //then\n        assertThat(result).isEmpty()\n    }\n\n    @Test\n    fun `inner path segment without leading slash`() {\n        //given\n        val specification = setOf(\n                Endpoint(\"/todo/list\", GET)\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.path.innerpathsegmentwithoutleadingslash\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `first path segment without leading slash`() {\n        //given\n        val specification = setOf(\n                Endpoint(\"/todo/list\", GET)\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.path.firstpathsegmentwithoutleadingslash\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterProducesTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterProducesTest {\n\n    @Nested\n    inner class DeclaredByControllerOnClass {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"text/plain\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onclass.onlycontroller.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"text/plain\",\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onclass.onlycontroller.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class ProducesOnClassOverridesController {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onclass.producesoverridescontroller.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"application/json\",\n                                    \"application/pdf\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onclass.producesoverridescontroller.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class DeclaredByProducesOnFunction {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"text/plain\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onfunction.onlyproduces.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"text/plain\",\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onfunction.onlyproduces.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    inner class ProducesOnFunctionOverridesController {\n\n        @Test\n        fun `single media type`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"application/xml\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onfunction.producesoverridescontroller.singlemediatype\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n\n        @Test\n        fun `multiple media types`() {\n            //given\n            val specification = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(\n                                    \"application/json\",\n                                    \"application/pdf\"\n                            )\n                    )\n            )\n\n            //when\n            val result = MicronautConverter(\"test.micronaut.produces.onfunction.producesoverridescontroller.multiplemediatypes\").conversionResult\n\n            //then\n            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Test\n    fun `use default media if no produces info has been set`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.produces.default\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterQueryParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\n\nclass MicronautConverterQueryParameterTest {\n\n    @Test\n    fun `query parameter required`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                                QueryParameter(\"filter\", true)\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.queryparameters.required.annotation\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `query parameter optional, because a default value exists`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                                QueryParameter(\"filter\", false)\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.queryparameters.optional\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `query is required and defined without annotation, because no matching template exists in url`() {\n        //given\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                                QueryParameter(\"filter\", false)\n                        )\n                )\n        )\n\n        //when\n        val result = MicronautConverter(\"test.micronaut.queryparameters.required.withoutannotation\").conversionResult\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/Todo.kt",
    "content": "package test.micronaut\n\ndata class Todo(val description: String = \"\")"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/default/ConsumesDefaultMediaTypeTestController.kt",
    "content": "package test.micronaut.consumes.default\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n@Controller(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesDefaultMediaTypeTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/consumesoverridescontroller/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.consumes.onclass.consumesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Consumes\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", consumes = [\"text/plain\", \"application/xml\"])\n@Consumes(\"application/json\", \"application/pdf\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesMultipleMediaTypesTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/consumesoverridescontroller/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.consumes.onclass.consumesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Consumes\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n\n@Consumes(\"application/xml\")\n@Controller(\"/todos\", consumes = [\"text/plain\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesSingleMediaTypeTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/onlycontroller/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.consumes.onclass.onlycontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", consumes = [\"text/plain\", \"application/xml\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesMultipleMediaTypesTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/onlycontroller/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.consumes.onclass.onlycontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n\n@Controller(\"/todos\", consumes = [\"text/plain\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesSingleMediaTypeTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/consumesoverridescontroller/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.consumes.onfunction.consumesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Consumes\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", consumes = [\"text/plain\", \"application/xml\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesMultipleMediaTypesTestController {\n\n    @Post\n    @Consumes(\"application/json\", \"application/pdf\")\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/consumesoverridescontroller/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.consumes.onfunction.consumesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Consumes\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n\n@Controller(\"/todos\", consumes = [\"text/plain\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesSingleMediaTypeTestController {\n\n    @Post\n    @Consumes(\"application/xml\")\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/onlyconsumes/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.consumes.onfunction.onlyconsumes.multiplemediatypes\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", consumes = [\"text/plain\", \"application/xml\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesMultipleMediaTypesTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/onlyconsumes/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.consumes.onfunction.onlyconsumes.singlemediatype\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\nimport test.micronaut.Todo\n\n\n@Controller(\"/todos\", consumes = [\"text/plain\"])\n@Suppress(\"UNUSED_PARAMETER\")\nclass ConsumesSingleMediaTypeTestController {\n\n    @Post\n    fun todos(@Body todo: Todo) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/deprecation/none/NoDeprecation.kt",
    "content": "package test.micronaut.deprecation.none\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todos\")\nclass NoDeprecation {\n\n    @Get\n    fun todo() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/deprecation/onclass/DeprecationOnClass.kt",
    "content": "package test.micronaut.deprecation.onclass\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todos\")\n@Deprecated(\"Test\")\nclass DeprecationOnClass {\n\n    @Get\n    fun todo() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/deprecation/onfunction/DeprecationOnFunction.kt",
    "content": "package test.micronaut.deprecation.onfunction\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todos\")\nclass DeprecationOnFunction {\n\n    @Get\n    @Deprecated(\"Test\")\n    fun todo() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/headerparameters/optional/HeaderParameterTestController.kt",
    "content": "package test.micronaut.headerparameters.optional\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Header\n\n@Controller(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass HeaderParameterTestController {\n\n    @Get\n    fun todos(@Header(\"allow-cache\", defaultValue = \"true\") otherName: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/headerparameters/required/HeaderParameterTestController.kt",
    "content": "package test.micronaut.headerparameters.required\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Header\n\n@Controller(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass HeaderParameterTestController {\n\n    @Get\n    fun todos(@Header(\"allow-cache\") otherName: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/delete/CombinedControllerAnnotationWithDeletePathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.delete\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Delete\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithDeletePathTestController {\n\n    @Delete(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/get/CombinedControllerAnnotationWithGetPathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.get\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithGetPathTestController {\n\n    @Get(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/head/CombinedControllerAnnotationWithHeadPathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.head\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Head\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithHeadPathTestController {\n\n    @Head(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/options/CombinedControllerAnnotationWithOptionsPathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.options\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Options\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithOptionsPathTestController {\n\n    @Options(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/patch/CombinedControllerAnnotationWithPatchPathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.patch\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Patch\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithPatchPathTestController {\n\n    @Patch(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/post/CombinedControllerAnnotationWithPostPathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.post\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithPostPathTestController {\n\n    @Post(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/put/CombinedControllerAnnotationWithPutPathTestController.kt",
    "content": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.put\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Put\n\n@Controller(\"/todo\")\nclass CombinedControllerAnnotationWithPutPathTestController {\n\n    @Put(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/firstpathsegmentwithoutleadingslash/FirstPathSegmentWithoutLeadingSlashTestController.kt",
    "content": "package test.micronaut.path.firstpathsegmentwithoutleadingslash\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"todo\")\nclass FirstPathSegmentWithoutLeadingSlashTestController {\n\n    @Get(\"/list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/innerpathsegmentwithoutleadingslash/InnerPathSegmentWithoutLeadingSlashTestController.kt",
    "content": "package test.micronaut.path.innerpathsegmentwithoutleadingslash\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todo\")\nclass InnerPathSegmentWithoutLeadingSlashTestController {\n\n    @Get(\"list\")\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/nohttpmethodannotation/NoHttpMethodAnnotationTestController.kt",
    "content": "package test.micronaut.path.nohttpmethodannotation\n\nimport io.micronaut.http.annotation.Controller\n\n@Controller(\"/todos\")\nclass NoHttpMethodAnnotationTestController {\n\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/delete/OnlyControllerAnnotationWithDeletePathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.delete\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Delete\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithDeletePathTestController {\n\n    @Delete\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/get/OnlyControllerAnnotationWithGetPathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.get\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithGetPathTestController {\n\n    @Get\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/head/OnlyControllerAnnotationWithHeadPathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.head\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Head\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithHeadPathTestController {\n\n    @Head\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/options/OnlyControllerAnnotationWithOptionsPathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.options\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Options\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithOptionsPathTestController {\n\n    @Options\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/patch/OnlyControllerAnnotationWithPatchPathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.patch\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Patch\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithPatchPathTestController {\n\n    @Patch\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/post/OnlyControllerAnnotationWithPostPathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.post\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Post\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithPostPathTestController {\n\n    @Post\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/put/OnlyControllerAnnotationWithPutPathTestController.kt",
    "content": "package test.micronaut.path.onlycontrollerannotation.put\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Put\n\n@Controller(\"/todos\")\nclass OnlyControllerAnnotationWithPutPathTestController {\n\n    @Put\n    fun todos() { }\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/pathparameters/annotation/name/PathParameterDefinedByAnnotationTestController.kt",
    "content": "package test.micronaut.pathparameters.annotation.name\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.PathVariable\n\n@Controller(\"/todos/{id}\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass PathParameterDefinedByAnnotationTestController {\n\n    @Get\n    fun todos(@PathVariable(name = \"id\") otherName: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/pathparameters/annotation/value/PathParameterDefinedByAnnotationTestController.kt",
    "content": "package test.micronaut.pathparameters.annotation.value\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.PathVariable\n\n@Controller(\"/todos/{id}\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass PathParameterDefinedByAnnotationTestController {\n\n    @Get\n    fun todos(@PathVariable(\"id\") otherName: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/pathparameters/variable/PathParameterDefinedByVariableNameTestController.kt",
    "content": "package test.micronaut.pathparameters.variable\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todos/{id}\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass PathParameterDefinedByVariableNameTestController {\n\n    @Get\n    fun todos(id: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/default/DefaultTestController.kt",
    "content": "package test.micronaut.produces.default\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport test.micronaut.Todo\n\n@Controller(\"/todos\")\nclass ProducesDefaultMediaTypeTestController {\n\n    @Get\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/onlycontroller/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.produces.onclass.onlycontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", produces = [\"text/plain\", \"application/xml\"])\nclass ProducesMultipleMediaTypesTestController {\n\n    @Get\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/onlycontroller/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.produces.onclass.onlycontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport test.micronaut.Todo\n\n\n@Controller(\"/todos\", produces = [\"text/plain\"])\nclass ProducesSingleMediaTypeTestController {\n\n    @Get\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/producesoverridescontroller/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.produces.onclass.producesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Produces\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", produces = [\"text/plain\", \"application/xml\"])\n@Produces(\"application/json\", \"application/pdf\")\nclass ProducesMultipleMediaTypesTestController {\n\n    @Get\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/producesoverridescontroller/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.produces.onclass.producesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Produces\nimport test.micronaut.Todo\n\n\n@Produces(\"application/xml\")\n@Controller(\"/todos\", produces = [\"text/plain\"])\nclass ProducesSingleMediaTypeTestController {\n\n    @Get\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/onlyproduces/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.produces.onfunction.onlyproduces.multiplemediatypes\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Produces\nimport test.micronaut.Todo\n\n@Controller(\"/todos\")\nclass ProducesMultipleMediaTypesTestController {\n\n    @Get\n    @Produces(\"text/plain\", \"application/xml\")\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/onlyproduces/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.produces.onfunction.onlyproduces.singlemediatype\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Produces\nimport test.micronaut.Todo\n\n@Controller(\"/todos\")\nclass ProducesSingleMediaTypeTestController {\n\n    @Get\n    @Produces(\"text/plain\")\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/producesoverridescontroller/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "content": "package test.micronaut.produces.onfunction.producesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Produces\nimport test.micronaut.Todo\n\n@Controller(\"/todos\", produces = [\"text/plain\", \"application/xml\"])\nclass ProducesMultipleMediaTypesTestController {\n\n    @Get\n    @Produces(\"application/json\", \"application/pdf\")\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/producesoverridescontroller/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "content": "package test.micronaut.produces.onfunction.producesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.Produces\nimport test.micronaut.Todo\n\n\n@Controller(\"/todos\", produces = [\"text/plain\"])\nclass ProducesSingleMediaTypeTestController {\n\n    @Get\n    @Produces(\"application/xml\")\n    fun todos() = Todo()\n}"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/queryparameters/optional/QueryParameterTestController.kt",
    "content": "package test.micronaut.queryparameters.optional\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.QueryValue\n\n@Controller(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass QueryParameterTestController {\n\n    @Get\n    fun todos(@QueryValue(\"filter\", defaultValue = \"all\") filter: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/queryparameters/required/annotation/QueryParameterTestController.kt",
    "content": "package test.micronaut.queryparameters.required.annotation\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\nimport io.micronaut.http.annotation.QueryValue\n\n@Controller(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass QueryParameterTestController {\n\n    @Get\n    fun todos(@QueryValue(\"filter\") filter: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/queryparameters/required/withoutannotation/QueryParameterTestController.kt",
    "content": "package test.micronaut.queryparameters.required.withoutannotation\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotation.Get\n\n@Controller(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nclass QueryParameterTestController {\n\n    @Get\n    fun todos(filter: String) { }\n}\n"
  },
  {
    "path": "micronaut/src/test/resources/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "openapi/README.md",
    "content": "# hikaku - OpenAPI\n\nSupports OpenAPI 3.0.X\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md). To check the feature support for this converter.\n\n## Usage\n\nThe OpenApiConverter can be used either with a `File` or a `Path` object. Both objects can relate to a `*.yaml`/`*.yml` or `*.json` file."
  },
  {
    "path": "openapi/build.gradle",
    "content": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-openapi'\n\ndependencies {\n  api project(':core')\n  api 'io.swagger.parser.v3:swagger-parser-v3:2.0.27'\n}\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-openapi'\n        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for OpenAPI specifications.'\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverter.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.AbstractEndpointConverter\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.converters.openapi.extensions.httpMethods\nimport de.codecentric.hikaku.converters.openapi.extractors.*\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod\nimport de.codecentric.hikaku.extensions.checkFileValidity\nimport io.swagger.v3.oas.models.Operation\nimport io.swagger.v3.parser.OpenAPIV3Parser\nimport java.io.File\nimport java.nio.charset.Charset\nimport java.nio.charset.StandardCharsets.UTF_8\nimport java.nio.file.Files.readAllLines\nimport java.nio.file.Path\n\n/**\n * Extracts and converts [Endpoint]s from OpenAPI 3.0.X document. Either a *.yaml*, *.yml* or a *.json* file.\n */\nclass OpenApiConverter private constructor(private val specificationContent: String) : AbstractEndpointConverter() {\n\n    @JvmOverloads\n    constructor(openApiSpecification: File, charset: Charset = UTF_8): this(openApiSpecification.toPath(), charset)\n    @JvmOverloads\n    constructor(openApiSpecification: Path, charset: Charset = UTF_8): this(readFileContent(openApiSpecification, charset))\n\n    override val supportedFeatures = SupportedFeatures(\n            Feature.QueryParameters,\n            Feature.PathParameters,\n            Feature.HeaderParameters,\n            Feature.Produces,\n            Feature.Consumes,\n            Feature.Deprecation\n    )\n\n    override fun convert(): Set<Endpoint> {\n        try {\n            return parseOpenApi()\n        } catch (throwable: Throwable) {\n            throw EndpointConverterException(throwable)\n        }\n    }\n\n    private fun parseOpenApi(): Set<Endpoint> {\n        val swaggerParseResult = OpenAPIV3Parser().readContents(specificationContent, null, null)\n\n        val openApi = swaggerParseResult.openAPI ?: throw openApiParseException(swaggerParseResult.messages)\n\n        val extractConsumesMediaTypes = ConsumesExtractor(openApi)\n        val extractProduceMediaTypes = ProducesExtractor(openApi)\n        val extractQueryParameters = QueryParameterExtractor(openApi)\n        val extractHeaderParameters = HeaderParameterExtractor(openApi)\n        val extractPathParameters = PathParameterExtractor(openApi)\n\n        return openApi.paths.flatMap { (path, pathItem) ->\n            val commonQueryParameters = extractQueryParameters(pathItem.parameters)\n            val commonPathParameters = extractPathParameters(pathItem.parameters)\n            val commonHeaderParameters = extractHeaderParameters(pathItem.parameters)\n\n            pathItem.httpMethods().map { (httpMethod: HttpMethod, operation: Operation?) ->\n                Endpoint(\n                        path = path,\n                        httpMethod = httpMethod,\n                        queryParameters = commonQueryParameters.union(extractQueryParameters(operation?.parameters)),\n                        pathParameters = commonPathParameters.union(extractPathParameters(operation?.parameters)),\n                        headerParameters = commonHeaderParameters.union(extractHeaderParameters(operation?.parameters)),\n                        consumes = extractConsumesMediaTypes(operation),\n                        produces = extractProduceMediaTypes(operation),\n                        deprecated = operation?.deprecated ?: false\n                )\n            }\n        }\n        .toSet()\n    }\n}\n\nprivate fun readFileContent(openApiSpecification: Path, charset: Charset): String {\n    try {\n        openApiSpecification.checkFileValidity(\".json\", \".yaml\", \".yml\")\n    } catch (throwable: Throwable) {\n        throw EndpointConverterException(throwable)\n    }\n    val fileContent = readAllLines(openApiSpecification, charset).joinToString(\"\\n\")\n\n    if (fileContent.isBlank()) {\n        throw EndpointConverterException(\"Given OpenAPI file is blank.\")\n    }\n\n    return fileContent\n}\n\nprivate fun openApiParseException(reasons: List<String>)\n    = EndpointConverterException(\"Failed to parse OpenAPI spec. Reasons:\\n${reasons.joinToString(\"\\n\")}\")"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extensions/PathItemExtensions.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extensions\n\nimport io.swagger.v3.oas.models.Operation\nimport io.swagger.v3.oas.models.PathItem\nimport de.codecentric.hikaku.endpoints.HttpMethod\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.HttpMethod.POST\nimport de.codecentric.hikaku.endpoints.HttpMethod.PATCH\nimport de.codecentric.hikaku.endpoints.HttpMethod.DELETE\nimport de.codecentric.hikaku.endpoints.HttpMethod.PUT\nimport de.codecentric.hikaku.endpoints.HttpMethod.OPTIONS\nimport de.codecentric.hikaku.endpoints.HttpMethod.HEAD\nimport de.codecentric.hikaku.endpoints.HttpMethod.TRACE\n\ninternal fun PathItem.httpMethods() = mapOf<HttpMethod, Operation?>(\n        GET to get,\n        POST to post,\n        PATCH to patch,\n        DELETE to delete,\n        PUT to put,\n        OPTIONS to options,\n        HEAD to head,\n        TRACE to trace\n).filterValues { it != null }\n"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extensions/ReferencedSchema.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extensions\n\nimport io.swagger.v3.oas.models.parameters.Parameter\nimport io.swagger.v3.oas.models.parameters.RequestBody\nimport io.swagger.v3.oas.models.responses.ApiResponse\n\n\ninternal val ApiResponse.referencedSchema\n    get() = `$ref`\n\ninternal val RequestBody.referencedSchema\n    get() = `$ref`\n\ninternal val Parameter.referencedSchema\n    get() = `$ref`"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/ConsumesExtractor.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions.referencedSchema\nimport io.swagger.v3.oas.models.OpenAPI\nimport io.swagger.v3.oas.models.Operation\n\ninternal class ConsumesExtractor(private val openApi: OpenAPI) {\n\n    operator fun invoke(operation: Operation?): Set<String> {\n        return operation?.requestBody\n                ?.content\n                ?.keys\n                .orEmpty()\n                .union(extractConsumesFromComponents(operation))\n                .toSet()\n    }\n\n    private fun extractConsumesFromComponents(operation: Operation?): Set<String> {\n        return operation?.requestBody\n                ?.referencedSchema\n                ?.let {\n                    Regex(\"#/components/requestBodies/(?<key>.+)\")\n                            .find(it)\n                            ?.groups\n                            ?.get(\"key\")\n                            ?.value\n                }\n                ?.let {\n                    openApi.components\n                            .requestBodies[it]\n                            ?.content\n                            ?.keys\n                }\n                .orEmpty()\n    }\n}"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/HeaderParameterExtractor.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions.referencedSchema\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport io.swagger.v3.oas.models.OpenAPI\nimport io.swagger.v3.oas.models.parameters.Parameter as OpenApiParameter\nimport io.swagger.v3.oas.models.parameters.HeaderParameter as OpenApiHeaderParameter\n\ninternal class HeaderParameterExtractor(private val openApi: OpenAPI) {\n\n    operator fun invoke(parameters: List<OpenApiParameter>?): Set<HeaderParameter> {\n        return extractInlineHeaderParameters(parameters).union(extractHeaderParametersFromComponents(parameters))\n    }\n\n    private fun extractInlineHeaderParameters(parameters: List<OpenApiParameter>?): Set<HeaderParameter> {\n        return parameters\n                ?.filterIsInstance<OpenApiHeaderParameter>()\n                ?.map { HeaderParameter(it.name, it.required) }\n                .orEmpty()\n                .toSet()\n    }\n\n    private fun extractHeaderParametersFromComponents(parameters: List<OpenApiParameter>?): Set<HeaderParameter> {\n        return parameters\n                ?.filter { it.referencedSchema != null }\n                ?.map {\n                    Regex(\"#/components/parameters/(?<key>.+)\")\n                            .find(it.referencedSchema)\n                            ?.groups\n                            ?.get(\"key\")\n                            ?.value\n                }\n                ?.map {\n                    openApi.components\n                            .parameters[it]\n                }\n                ?.filter { it?.`in` == \"header\" }\n                ?.map { HeaderParameter(it?.name ?: \"\", it?.required ?: false) }\n                .orEmpty()\n                .toSet()\n    }\n}"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/PathParameterExtractor.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions.referencedSchema\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport io.swagger.v3.oas.models.OpenAPI\nimport io.swagger.v3.oas.models.parameters.PathParameter as OpenApiPathParameter\nimport io.swagger.v3.oas.models.parameters.Parameter as OpenApiParameter\n\ninternal class PathParameterExtractor(private val openApi: OpenAPI) {\n\n    operator fun invoke(parameters: List<OpenApiParameter>?): Set<PathParameter> {\n        return extractInlinePathParameters(parameters).union(extractPathParametersFromComponents(parameters))\n    }\n\n    private fun extractInlinePathParameters(parameters: List<OpenApiParameter>?): Set<PathParameter> {\n        return parameters\n                ?.filterIsInstance<OpenApiPathParameter>()\n                ?.map { PathParameter(it.name) }\n                .orEmpty()\n                .toSet()\n    }\n\n    private fun extractPathParametersFromComponents(parameters: List<OpenApiParameter>?): Set<PathParameter> {\n        return parameters\n                ?.filter { it.referencedSchema != null }\n                ?.map {\n                    Regex(\"#/components/parameters/(?<key>.+)\")\n                            .find(it.referencedSchema)\n                            ?.groups\n                            ?.get(\"key\")\n                            ?.value\n                }\n                ?.map {\n                    openApi.components\n                            .parameters[it]\n                }\n                ?.filter { it?.`in` == \"path\" }\n                ?.map { PathParameter(it?.name ?: \"\") }\n                .orEmpty()\n                .toSet()\n    }\n}"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/ProducesExtractor.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions.referencedSchema\nimport io.swagger.v3.oas.models.OpenAPI\nimport io.swagger.v3.oas.models.Operation\n\ninternal class ProducesExtractor(private val openApi: OpenAPI) {\n\n    operator fun invoke(operation: Operation?): Set<String> {\n        return operation?.responses\n                ?.flatMap {\n                    it.value\n                            ?.content\n                            ?.keys\n                            .orEmpty()\n                }\n                .orEmpty()\n                .union(extractResponsesFromComponents(operation))\n                .toSet()\n    }\n\n    private fun extractResponsesFromComponents(operation: Operation?): Set<String> {\n        return operation?.responses\n                ?.mapNotNull { it.value.referencedSchema }\n                ?.map {\n                    Regex(\"#/components/responses/(?<key>.+)\")\n                            .find(it)\n                            ?.groups\n                            ?.get(\"key\")\n                            ?.value\n                }\n                ?.flatMap {\n                    openApi.components\n                            .responses[it]\n                            ?.content\n                            ?.keys\n                            .orEmpty()\n                }\n                .orEmpty()\n                .toSet()\n    }\n}"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/QueryParameterExtractor.kt",
    "content": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions.referencedSchema\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport io.swagger.v3.oas.models.OpenAPI\nimport io.swagger.v3.oas.models.parameters.Parameter as OpenApiParameter\nimport io.swagger.v3.oas.models.parameters.QueryParameter as OpenApiQueryParameter\n\ninternal class QueryParameterExtractor(private val openApi: OpenAPI) {\n\n    operator fun invoke(parameters: List<OpenApiParameter>?): Set<QueryParameter> {\n        return extractInlineQueryParameters(parameters).union(extractQueryParametersFromComponents(parameters))\n    }\n\n    private fun extractInlineQueryParameters(parameters: List<OpenApiParameter>?): Set<QueryParameter> {\n        return parameters\n                ?.filterIsInstance<OpenApiQueryParameter>()\n                ?.map { QueryParameter(it.name, it.required) }\n                .orEmpty()\n                .toSet()\n    }\n\n    private fun extractQueryParametersFromComponents(parameters: List<OpenApiParameter>?): Set<QueryParameter> {\n        return parameters\n                ?.filter { it.referencedSchema != null }\n                ?.map {\n                    Regex(\"#/components/parameters/(?<key>.+)\")\n                            .find(it.referencedSchema)\n                            ?.groups\n                            ?.get(\"key\")\n                            ?.value\n                }\n                ?.map {\n                    openApi.components\n                            .parameters[it]\n                }\n                ?.filter { it?.`in` == \"query\" }\n                ?.map { QueryParameter(it?.name ?: \"\", it?.required ?: false) }\n                .orEmpty()\n                .toSet()\n    }\n}"
  },
  {
    "path": "openapi/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterConsumesTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.POST\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterConsumesTest {\n\n    @Test\n    fun `inline declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/consumes_inline.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = POST,\n                        consumes = setOf(\"application/xml\")\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `response is declared in components section`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/consumes_requestbody_in_components.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = POST,\n                        consumes = setOf(\"application/xml\")\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterDeprecationTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterDeprecationTest {\n\n    @Test\n    fun `no deprecation`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"deprecation/deprecation_none.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"application/json\"),\n                        deprecated = false\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `deprecated operation`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"deprecation/deprecation_operation.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"application/json\"),\n                        deprecated = true\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterEndpointTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterEndpointTest {\n\n    @Test\n    fun `extract two different paths`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"endpoints/endpoints_two_different_paths.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/tags\", GET)\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `extract two paths of which one is nested`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"endpoints/endpoints_two_nested_paths.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/todos/query\", GET)\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `extract all http methods`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"endpoints/endpoints_all_http_methods.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/todos\", POST),\n                Endpoint(\"/todos\", PUT),\n                Endpoint(\"/todos\", PATCH),\n                Endpoint(\"/todos\", DELETE),\n                Endpoint(\"/todos\", HEAD),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\"/todos\", TRACE)\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterHeaderParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterHeaderParameterTest {\n\n    @Test\n    fun `header parameter inline declaration on Operation object`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"header_parameter/header_parameter_inline.yaml\").toURI())\n        val headerParameters = setOf(\n                HeaderParameter(\"x-b3-traceid\", false),\n                HeaderParameter(\"allow-cache\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].headerParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(headerParameters)\n    }\n\n    @Test\n    fun `one header parameter declared inline and one parameter referenced from parameters section in components`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"header_parameter/header_parameter_in_components.yaml\").toURI())\n        val headerParameters = setOf(\n                HeaderParameter(\"x-b3-traceid\", false),\n                HeaderParameter(\"allow-cache\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].headerParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(headerParameters)\n    }\n\n    @Test\n    fun `common header parameter inline declaration on Operation object`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"header_parameter/common_header_parameter_inline.yaml\").toURI())\n        val headerParameters = setOf(\n                HeaderParameter(\"x-b3-traceid\", false),\n                HeaderParameter(\"allow-cache\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].headerParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(headerParameters)\n    }\n\n    @Test\n    fun `one common header parameter declared inline and one parameter referenced from parameters section in components`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"header_parameter/common_header_parameter_in_components.yaml\").toURI())\n        val headerParameters = setOf(\n                HeaderParameter(\"x-b3-traceid\", false),\n                HeaderParameter(\"allow-cache\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].headerParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(headerParameters)\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterInvalidInputTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport java.io.File\nimport java.nio.file.Paths\nimport kotlin.test.assertFailsWith\n\nclass OpenApiConverterInvalidInputTest {\n\n    @Nested\n    inner class PathObjectTests {\n\n        @Test\n        fun `empty file returns an empty list`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/empty_file.yaml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                OpenApiConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file consisting solely of whitespaces returns an empty list`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/whitespaces_only_file.yaml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                OpenApiConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `OpenAPI yaml file containing syntax error`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/syntax_error.yaml\").toURI())\n            val converter = OpenApiConverter(file)\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                converter.conversionResult\n            }\n        }\n    }\n\n    @Nested\n    inner class FileObjectTests {\n\n        @Test\n        fun `empty file returns an empty list`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/empty_file.yaml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                OpenApiConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file consisting solely of whitespaces returns an empty list`() {\n            //given\n                val file = File(this::class.java.classLoader.getResource(\"invalid_input/whitespaces_only_file.yaml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                OpenApiConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `OpenAPI yaml file containing syntax error`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/syntax_error.yaml\").toURI())\n            val converter = OpenApiConverter(file)\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                converter.conversionResult\n            }\n        }\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterPathParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterPathParameterTest {\n\n    @Test\n    fun `path parameter inline declaration on Operation object`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameter/path_parameter_inline.yaml\").toURI())\n        val pathParameter = PathParameter(\"id\")\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()\n\n        //then\n        assertThat(result[0].pathParameters).containsExactly(pathParameter)\n        assertThat(result[1].pathParameters).containsExactly(pathParameter)\n        assertThat(result[2].pathParameters).containsExactly(pathParameter)\n    }\n\n    @Test\n    fun `one path parameter declared inline and two parameters referenced from parameters section in components`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameter/path_parameter_in_components.yaml\").toURI())\n        val pathParameter = PathParameter(\"id\")\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()\n\n        //then\n        assertThat(result[0].pathParameters).containsExactly(pathParameter)\n        assertThat(result[1].pathParameters).containsExactly(pathParameter)\n        assertThat(result[2].pathParameters).containsExactly(pathParameter)\n    }\n\n    @Test\n    fun `common path parameter inline declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameter/common_path_parameter_inline.yaml\").toURI())\n        val pathParameter = PathParameter(\"id\")\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()\n\n        //then\n        assertThat(result[0].pathParameters).containsExactly(pathParameter)\n        assertThat(result[1].pathParameters).containsExactly(pathParameter)\n        assertThat(result[2].pathParameters).containsExactly(pathParameter)\n    }\n\n    @Test\n    fun `common path parameter referenced from parameters section in components`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameter/common_path_parameter_in_components.yaml\").toURI())\n        val pathParameter = PathParameter(\"id\")\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()\n\n        //then\n        assertThat(result[0].pathParameters).containsExactly(pathParameter)\n        assertThat(result[1].pathParameters).containsExactly(pathParameter)\n        assertThat(result[2].pathParameters).containsExactly(pathParameter)\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterProducesTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.DELETE\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterProducesTest {\n\n    @Test\n    fun `inline declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_inline.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"application/json\")\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `no content-type`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_no_content_type.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\"/todos\", DELETE)\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `response is declared in components section`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_response_in_components.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"application/xml\")\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `produces having a default value`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_with_default.yaml\").toURI())\n        val implementation = setOf(\n                Endpoint(\n                        path = \"/todos/query\",\n                        httpMethod = GET,\n                        produces = setOf(\"application/json\", \"text/plain\")\n                )\n        )\n\n        //when\n        val specification = OpenApiConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n}"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterQueryParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass OpenApiConverterQueryParameterTest {\n\n    @Test\n    fun `query parameter inline declaration on Operation object`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"query_parameter/query_parameter_inline.yaml\").toURI())\n        val queryParameters = setOf(\n                QueryParameter(\"tag\", false),\n                QueryParameter(\"limit\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].queryParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(queryParameters)\n    }\n\n    @Test\n    fun `one query parameter declared inline and one parameter referenced from parameters section in components`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"query_parameter/query_parameter_in_components.yaml\").toURI())\n        val queryParameters = setOf(\n                QueryParameter(\"tag\", false),\n                QueryParameter(\"limit\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].queryParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(queryParameters)\n    }\n\n    @Test\n    fun `common query parameter inline declaration on Operation object`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"query_parameter/common_query_parameter_inline.yaml\").toURI())\n        val queryParameters = setOf(\n                QueryParameter(\"tag\", false),\n                QueryParameter(\"limit\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].queryParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(queryParameters)\n    }\n\n    @Test\n    fun `one query parameter declared inline and one common parameter referenced from parameters section in components`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"query_parameter/common_query_parameter_in_components.yaml\").toURI())\n        val queryParameters = setOf(\n                QueryParameter(\"tag\", false),\n                QueryParameter(\"limit\", true)\n        )\n\n        //when\n        val result = OpenApiConverter(file).conversionResult.toList()[0].queryParameters\n\n        //then\n        assertThat(result).containsExactlyInAnyOrderElementsOf(queryParameters)\n    }\n}"
  },
  {
    "path": "openapi/src/test/resources/consumes/consumes_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    post:\n      description: ''\n      requestBody:\n        content:\n          'application/xml':\n            schema:\n              $ref: '#/components/schemas/Todo'\n      responses:\n        '200':\n          description: OK\ncomponents:\n  schemas:\n    Todo:\n      type: array\n      items:\n        type: string"
  },
  {
    "path": "openapi/src/test/resources/consumes/consumes_requestbody_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    post:\n      description: ''\n      requestBody:\n        $ref: '#/components/requestBodies/TodoRequest'\n      responses:\n        '200':\n          description: ''\ncomponents:\n  requestBodies:\n    TodoRequest:\n      description: A complex object array response\n      content:\n        application/xml:\n          schema:\n            type: array\n            items:\n              $ref: '#/components/schemas/Todo'\n  schemas:\n    Todo:\n      type: array\n      items:\n        type: string\n    NotFoundModel:\n      type: string"
  },
  {
    "path": "openapi/src/test/resources/deprecation/deprecation_none.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      deprecated: false\n      description: ''\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  type: string"
  },
  {
    "path": "openapi/src/test/resources/deprecation/deprecation_operation.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      deprecated: true\n      description: ''\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  type: string"
  },
  {
    "path": "openapi/src/test/resources/endpoints/endpoints_all_http_methods.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    post:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    put:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    patch:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    delete:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    head:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    options:\n      description: ''\n      responses:\n        '200':\n          description: OK\n    trace:\n      description: ''\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/endpoints/endpoints_two_different_paths.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK\n  /tags:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/endpoints/endpoints_two_nested_paths.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK\n  /todos/query:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/header_parameter/common_header_parameter_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - name: x-b3-traceid\n        in: header\n        required: false\n        description: \"Trace id.\"\n        schema:\n          type: string\n      - $ref: \"#/components/parameters/allowCacheParam\"\n    get:\n      description: 'Get all todos'\n      responses:\n        '200':\n          description: OK\ncomponents:\n  parameters:\n    allowCacheParam:\n      name: allow-cache\n      in: header\n      required: true\n      description: \"Whether cached data is allowed or not.\"\n      schema:\n        type: boolean"
  },
  {
    "path": "openapi/src/test/resources/header_parameter/common_header_parameter_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - name: x-b3-traceid\n        in: header\n        required: false\n        description: \"Trace id.\"\n        schema:\n          type: string\n      - name: allow-cache\n        in: header\n        required: true\n        description: \"Whether cached data is allowed or not.\"\n        schema:\n          type: boolean\n    get:\n      description: 'Get all todos'\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/header_parameter/header_parameter_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: x-b3-traceid\n          in: header\n          required: false\n          description: \"Trace id.\"\n          schema:\n            type: string\n        - $ref: \"#/components/parameters/allowCacheParam\"\n      responses:\n        '200':\n          description: OK\ncomponents:\n  parameters:\n    allowCacheParam:\n      name: allow-cache\n      in: header\n      required: true\n      description: \"Whether cached data is allowed or not.\"\n      schema:\n        type: boolean"
  },
  {
    "path": "openapi/src/test/resources/header_parameter/header_parameter_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: x-b3-traceid\n          in: header\n          required: false\n          description: \"Trace id.\"\n          schema:\n            type: string\n        - name: allow-cache\n          in: header\n          required: true\n          description: \"Whether cached data is allowed or not.\"\n          schema:\n            type: boolean\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/invalid_input/empty_file.yaml",
    "content": ""
  },
  {
    "path": "openapi/src/test/resources/invalid_input/syntax_error.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  title: Todo List\npaths:\n  todos\n    get\n      summary: Add a new todo\n      description: 'Creates a new todo.'\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/invalid_input/whitespaces_only_file.yaml",
    "content": "                                   "
  },
  {
    "path": "openapi/src/test/resources/path_parameter/common_path_parameter_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    parameters:\n      - $ref: \"#/components/parameters/todoIdParam\"\n    get:\n      description: 'Get all todos'\n      responses:\n        '200':\n          description: OK\n    post:\n      description: 'Create a new todo.'\n      responses:\n        '200':\n          description: OK\n    delete:\n      description: 'Delete a todo entry.'\n      responses:\n        '200':\n          description: OK\ncomponents:\n  parameters:\n    todoIdParam:\n      name: id\n      in: path\n      required: true\n      description: \"Identifier of a specific todo entry.\"\n      schema:\n        type: integer\n        format: int32"
  },
  {
    "path": "openapi/src/test/resources/path_parameter/common_path_parameter_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    parameters:\n      - name: id\n        in: path\n        required: true\n        description: \"Identifier of a specific todo entry.\"\n        schema:\n          type: integer\n          format: int32\n    get:\n      description: 'Get all todos'\n      responses:\n        '200':\n          description: OK\n    post:\n      description: 'Create a new todo.'\n      responses:\n        '200':\n          description: OK\n    delete:\n      description: 'Delete a todo entry.'\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/path_parameter/path_parameter_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: id\n          in: path\n          required: true\n          description: \"Identifier of a specific todo entry.\"\n          schema:\n            type: integer\n            format: int32\n      responses:\n        '200':\n          description: OK\n    post:\n      description: 'Create a new todo.'\n      parameters:\n        - $ref: \"#/components/parameters/todoIdParam\"\n      responses:\n        '200':\n          description: OK\n    delete:\n      description: 'Delete a todo entry.'\n      parameters:\n        - $ref: \"#/components/parameters/todoIdParam\"\n      responses:\n        '200':\n          description: OK\ncomponents:\n  parameters:\n    todoIdParam:\n      name: id\n      in: path\n      required: true\n      description: \"Identifier of a specific todo entry.\"\n      schema:\n        type: integer\n        format: int32"
  },
  {
    "path": "openapi/src/test/resources/path_parameter/path_parameter_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: id\n          in: path\n          required: true\n          description: \"Identifier of a specific todo entry.\"\n          schema:\n            type: integer\n            format: int32\n      responses:\n        '200':\n          description: OK\n    post:\n      description: 'Create a new todo.'\n      parameters:\n        - name: id\n          in: path\n          required: true\n          description: \"Identifier of a specific todo entry.\"\n          schema:\n            type: integer\n            format: int32\n      responses:\n        '200':\n          description: OK\n    delete:\n      description: 'Delete a todo entry.'\n      parameters:\n        - name: id\n          in: path\n          required: true\n          description: \"Identifier of a specific todo entry.\"\n          schema:\n            type: integer\n            format: int32\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Todo'\ncomponents:\n  schemas:\n    Todo:\n      type: array\n      items:\n        type: string"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_no_content_type.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    delete:\n      description: 'Delete all todos'\n      responses:\n        '204':\n          description: ''"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_response_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses:\n        '200':\n          $ref: '#/components/responses/TodoResponse'\ncomponents:\n  responses:\n    TodoResponse:\n      description: A complex object array response\n      content:\n        application/xml:\n          schema:\n            type: array\n            items:\n              $ref: '#/components/schemas/Todo'\n  schemas:\n    Todo:\n      type: array\n      items:\n        type: string\n    NotFoundModel:\n      type: string"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_with_default.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/query:\n    get:\n      description: ''\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Todo'\n        default:\n          description: No data\n          content:\n            text/plain:\n              schema:\n                $ref: '#/components/schemas/NotFoundModel'\ncomponents:\n  responses:\n    TodoResponse:\n      description: A complex object array response\n      content:\n        application/xml:\n          schema:\n            type: array\n            items:\n              $ref: '#/components/schemas/Todo'\n  schemas:\n    Todo:\n      type: array\n      items:\n        type: string\n    NotFoundModel:\n      type: string"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/common_query_parameter_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - $ref: \"#/components/parameters/limitParam\"\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: tag\n          in: query\n          required: false\n          description: \"Filter todos by a given tag.\"\n          schema:\n            type: string\n      responses:\n        '200':\n          description: OK\ncomponents:\n  parameters:\n    limitParam:\n      name: limit\n      in: query\n      required: true\n      description: \"Limit\"\n      schema:\n        type: number\n        format: int32"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/common_query_parameter_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - name: limit\n        in: query\n        required: true\n        description: \"Limit\"\n        schema:\n          type: number\n          format: int32\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: tag\n          in: query\n          required: false\n          description: \"Filter todos by a given tag.\"\n          schema:\n            type: string\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/query_parameter_in_components.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: tag\n          in: query\n          required: false\n          description: \"Filter todos by a given tag.\"\n          schema:\n            type: string\n        - $ref: \"#/components/parameters/limitParam\"\n      responses:\n        '200':\n          description: OK\ncomponents:\n  parameters:\n    limitParam:\n      name: limit\n      in: query\n      required: true\n      description: \"Limit\"\n      schema:\n        type: number\n        format: int32"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/query_parameter_inline.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n      parameters:\n        - name: tag\n          in: query\n          required: false\n          description: \"Filter todos by a given tag.\"\n          schema:\n            type: string\n        - name: limit\n          in: query\n          required: true\n          description: \"Limit\"\n          schema:\n            type: number\n            format: int32\n      responses:\n        '200':\n          description: OK"
  },
  {
    "path": "raml/README.md",
    "content": "# hikaku - RAML\n\nSupports RAML 1.X\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md). To check the feature support for this converter.\n\n## Currently not supported\n\n* Query string declaration\n  * see https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#query-strings-and-query-parameters\n\n## Usage\n\nThe RamlConverter can be used either with a `File` or a `Path` object."
  },
  {
    "path": "raml/build.gradle",
    "content": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-raml'\n\ndependencies {\n  api project(':core')\n  api 'org.raml:raml-parser-2:1.0.51'\n\n\n  testImplementation \"io.mockk:mockk:1.12.0\"\n}\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-raml'\n        description = 'A library to test if the implementation of a REST-API meets its specification. This module contains a converter for raml specifications.'\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "raml/src/main/kotlin/de/codecentric/hikaku/converters/raml/RamlConverter.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.AbstractEndpointConverter\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.converters.raml.extensions.*\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.extensions.checkFileValidity\nimport org.raml.v2.api.RamlModelBuilder\nimport org.raml.v2.api.RamlModelResult\nimport org.raml.v2.api.model.v10.resources.Resource\nimport java.io.File\nimport java.nio.file.Path\n\nclass RamlConverter(private val ramlSpecification: File) : AbstractEndpointConverter()  {\n\n    constructor(ramlSpecification: Path) : this(ramlSpecification.toFile())\n\n    override val supportedFeatures = SupportedFeatures(\n            Feature.QueryParameters,\n            Feature.PathParameters,\n            Feature.HeaderParameters,\n            Feature.Produces,\n            Feature.Consumes,\n            Feature.Deprecation\n    )\n\n    override fun convert(): Set<Endpoint> {\n        val ramlParserResult: RamlModelResult?\n\n        try {\n            ramlSpecification.checkFileValidity(\".raml\")\n            ramlParserResult = RamlModelBuilder().buildApi(ramlSpecification)\n        } catch(throwable: Throwable) {\n            throw EndpointConverterException(throwable)\n        }\n\n        if (ramlParserResult.isVersion08) {\n            throw EndpointConverterException(\"Unsupported RAML version\")\n        }\n\n        if (ramlParserResult.hasErrors()) {\n            throw EndpointConverterException(ramlParserResult.validationResults.joinToString(\"\\n\"))\n        }\n\n        return ramlParserResult.apiV10?.resources()?.let { resourceList ->\n            resourceList.flatMap { findEndpoints(it) }\n        }\n        .orEmpty()\n        .toSet()\n    }\n\n    private fun findEndpoints(resource: Resource): List<Endpoint> {\n        val endpoints = mutableListOf<Endpoint>()\n\n        if (resource.resources().isNotEmpty()) {\n            endpoints += resource.resources().flatMap {\n                return@flatMap findEndpoints(it)\n            }\n        }\n\n        if (resource.methods().isNotEmpty()) {\n            endpoints += resource.methods().map {\n                    Endpoint(\n                            path = resource.resourcePath(),\n                            httpMethod = it.hikakuHttpMethod(),\n                            queryParameters = it.hikakuQueryParameters(),\n                            pathParameters = it.resource()?.hikakuPathParameters().orEmpty(),\n                            headerParameters = it?.hikakuHeaderParameters().orEmpty(),\n                            consumes = it.requestMediaTypes(),\n                            produces = it.responseMediaTypes(),\n                            deprecated = it.isEndpointDeprecated()\n                    )\n            }\n        }\n\n        return endpoints\n    }\n}"
  },
  {
    "path": "raml/src/main/kotlin/de/codecentric/hikaku/converters/raml/extensions/MethodExtensions.kt",
    "content": "package de.codecentric.hikaku.converters.raml.extensions\n\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport de.codecentric.hikaku.endpoints.HttpMethod\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.raml.v2.api.model.v10.methods.Method\n\ninternal fun Method.hikakuHttpMethod() = HttpMethod.valueOf(this.method().uppercase())\n\ninternal fun Method.hikakuQueryParameters(): Set<QueryParameter> {\n    return this.queryParameters()\n            .map {\n                QueryParameter(it.name(), it.required())\n            }\n            .toSet()\n}\n\ninternal fun Method.hikakuHeaderParameters(): Set<HeaderParameter> {\n    return this.headers()\n            .map {\n                HeaderParameter(it.name(), it.required())\n            }\n            .toSet()\n}\n\ninternal fun Method.requestMediaTypes(): Set<String> {\n    return this.body().map {\n        it.name()\n    }\n    .toSet()\n}\n\ninternal fun Method.responseMediaTypes(): Set<String> {\n    return this.responses().flatMap {response ->\n        response.body().map { it.name() }\n    }\n            .toSet()\n}\n\ninternal fun Method.isEndpointDeprecated() =\n        this.annotations().any { i -> i.annotation().name() == \"deprecated\" }\n                || checkNotNull(this.resource()).annotations().any { i -> i.annotation().name() == \"deprecated\" }"
  },
  {
    "path": "raml/src/main/kotlin/de/codecentric/hikaku/converters/raml/extensions/ResourceExtensions.kt",
    "content": "package de.codecentric.hikaku.converters.raml.extensions\n\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.raml.v2.api.model.v10.resources.Resource\n\nfun Resource.hikakuPathParameters(): Set<PathParameter> {\n    return this.uriParameters()\n            .map {\n                PathParameter(it.name())\n            }\n            .toSet()\n}"
  },
  {
    "path": "raml/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterConsumesTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\nimport kotlin.test.assertFailsWith\n\nclass RamlConverterConsumesTest {\n\n    @Test\n    fun `no media type`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/no_media_type.raml\").toURI())\n\n        //when\n        assertFailsWith<EndpointConverterException> {\n            RamlConverter(file).conversionResult\n        }\n    }\n\n    @Test\n    fun `single default media type`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/single_default_media_type.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple default media types`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/multiple_default_media_types.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `single method declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/single_method_declaration.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple method declarations`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/multiple_method_declarations.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `method declaration overwrites default`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/method_declaration_overwrites_default.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterDeprecationTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass RamlConverterDeprecationTest {\n\n    @Test\n    fun `no deprecations`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"deprecation/none.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"text/plain\"),\n                        deprecated = false\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `deprecated resource`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"deprecation/on_resource.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"text/plain\"),\n                        deprecated = true\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `deprecated method`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"deprecation/on_method.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\"text/plain\"),\n                        deprecated = true\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterHeaderParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass RamlConverterHeaderParameterTest {\n\n    @Test\n    fun `extract an optional and a required header parameter`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"header_parameter.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path =\"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                                HeaderParameter(\"allow-cache\", true),\n                                HeaderParameter(\"x-b3-traceid\", false)\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterHttpMethodTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass RamlConverterHttpMethodTest {\n\n    @Test\n    fun `extract all supported http methods`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"http_method/http_methods.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/todos\", POST),\n                Endpoint(\"/todos\", PUT),\n                Endpoint(\"/todos\", PATCH),\n                Endpoint(\"/todos\", DELETE),\n                Endpoint(\"/todos\", HEAD),\n                Endpoint(\"/todos\", OPTIONS)\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `path without http methods does not create an endpoint`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"http_method/path_without_http_method.raml\").toURI())\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).isEmpty()\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterInvalidInputTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport java.io.File\nimport java.nio.file.Paths\nimport kotlin.test.assertFailsWith\n\nclass RamlConverterInvalidInputTest {\n\n    @Nested\n    inner class FileObjectTests {\n\n        @Test\n        fun `empty file returns an empty list`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/empty_file.raml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                RamlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file consisting solely of whitespaces returns an empty list`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/whitespaces_only_file.raml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                RamlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `invalid RAML version`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/invalid_raml_version.raml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                RamlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file containing syntax error throws SpecificationParserException`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/syntax_error.raml\").toURI())\n            val converter = RamlConverter(file)\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                converter.conversionResult\n            }\n        }\n    }\n\n    @Nested\n    inner class PathObjectTests {\n\n        @Test\n        fun `empty file returns an empty list`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/empty_file.raml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                RamlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file consisting solely of whitespaces returns an empty list`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/whitespaces_only_file.raml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                RamlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `invalid RAML version`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/invalid_raml_version.raml\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                RamlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file containing syntax error`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/syntax_error.raml\").toURI())\n            val converter = RamlConverter(file)\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                converter.conversionResult\n            }\n        }\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterPathParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.HttpMethod.POST\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass RamlConverterPathParameterTest {\n\n    @Test\n    fun `simple path parameter declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameter/simple_path_parameter.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos/{id}\",\n                        httpMethod = GET,\n                        pathParameters = setOf(\n                                PathParameter(\"id\")\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `nested path parameter declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameter/nested_path_parameter.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\"/todos\", POST),\n                Endpoint(\n                        path = \"/todos/{id}\",\n                        httpMethod = GET,\n                        pathParameters = setOf(\n                                PathParameter(\"id\")\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterPathTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.HttpMethod.POST\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass RamlConverterPathTest {\n\n    @Test\n    fun `simple path`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path/simple_path.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\"/todos\", GET)\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `extract nested paths`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path/nested_path.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\"/todo\", POST),\n                Endpoint(\"/todo/list\", GET)\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `extract nested paths defined in a single entry`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path/nested_path_single_entry.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\"/todo/list\", POST),\n                Endpoint(\"/todo/list\", GET)\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterProducesTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\nimport kotlin.test.assertFailsWith\n\nclass RamlConverterProducesTest {\n\n    @Test\n    fun `no media type`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/no_media_type.raml\").toURI())\n\n        //when\n        assertFailsWith<EndpointConverterException> {\n            RamlConverter(file).conversionResult\n        }\n    }\n\n    @Test\n    fun `single default media type`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/single_default_media_type.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple default media types`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/multiple_default_media_types.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `single method declaration`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/single_method_declaration.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `multiple method declarations`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/multiple_method_declarations.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"application/xml\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n\n    @Test\n    fun `method declaration overwrites default`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/method_declaration_overwrites_default.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterQueryParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass RamlConverterQueryParameterTest {\n\n    @Test\n    fun `extracts required and optional query parameter`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"query_parameter/query_parameter.raml\").toURI())\n\n        val specification = setOf(\n                Endpoint(\n                        path =\"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                                QueryParameter(\"limit\", true),\n                                QueryParameter(\"tag\", false)\n                        )\n                )\n        )\n\n        //when\n        val implementation = RamlConverter(file).conversionResult\n\n        //then\n        assertThat(implementation).containsExactlyInAnyOrderElementsOf(specification)\n    }\n}"
  },
  {
    "path": "raml/src/test/resources/consumes/method_declaration_overwrites_default.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nmediaType: [application/json, application/xml]\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      text/plain:\n        type: string"
  },
  {
    "path": "raml/src/test/resources/consumes/multiple_default_media_types.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nmediaType: [application/json, application/xml]\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      type: string"
  },
  {
    "path": "raml/src/test/resources/consumes/multiple_method_declarations.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      application/json:\n        type: string\n      application/xml:\n        type: string"
  },
  {
    "path": "raml/src/test/resources/consumes/no_media_type.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      type: string"
  },
  {
    "path": "raml/src/test/resources/consumes/single_default_media_type.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nmediaType: application/json\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      type: string"
  },
  {
    "path": "raml/src/test/resources/consumes/single_method_declaration.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      text/plain:\n        type: string"
  },
  {
    "path": "raml/src/test/resources/deprecation/none.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nannotationTypes:\n  deprecated: string\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          text/plain:\n            type: string"
  },
  {
    "path": "raml/src/test/resources/deprecation/on_method.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nannotationTypes:\n  deprecated: string\n/todos:\n  displayName: Todos\n  get:\n    (deprecated): This method is deprecated\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          text/plain:\n            type: string"
  },
  {
    "path": "raml/src/test/resources/deprecation/on_resource.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nannotationTypes:\n  deprecated: string\n/todos:\n  (deprecated): This endpoint is deprecated\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          text/plain:\n            type: string"
  },
  {
    "path": "raml/src/test/resources/header_parameter.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    headers:\n      x-b3-traceid:\n        displayName: x-b3-traceid\n        type: string\n        required: false\n      allow-cache:\n        displayName: allow-cache\n        type: string\n        required: true"
  },
  {
    "path": "raml/src/test/resources/http_method/http_methods.raml",
    "content": "#%RAML 1.0\ntitle: test api\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n  post:\n    displayName: Create a new todo\n  put:\n    displayName: Create or update a todo\n  patch:\n    displayName: Partially update a todo\n  delete:\n    displayName: Delete a todo\n  head:\n    displayName: check endpoint\n  options:\n    displayName: get allowed methods"
  },
  {
    "path": "raml/src/test/resources/http_method/path_without_http_method.raml",
    "content": "#%RAML 1.0\ntitle: test api\n/todos:\n  displayName: Todos"
  },
  {
    "path": "raml/src/test/resources/invalid_input/different_extension.css",
    "content": ""
  },
  {
    "path": "raml/src/test/resources/invalid_input/empty_file.raml",
    "content": ""
  },
  {
    "path": "raml/src/test/resources/invalid_input/invalid_raml_version.raml",
    "content": "#%RAML 0.8\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:"
  },
  {
    "path": "raml/src/test/resources/invalid_input/syntax_error.raml",
    "content": "#%RAML 1.0\ntitle: test api\n/todos:\n  displayN Todos\n  ge"
  },
  {
    "path": "raml/src/test/resources/invalid_input/whitespaces_only_file.raml",
    "content": "                                   "
  },
  {
    "path": "raml/src/test/resources/path/nested_path.raml",
    "content": "#%RAML 1.0\ntitle: test api\n/todo:\n  displayName: Todos\n  post:\n    displayName: Create a new todo\n  /list:\n    get:\n        displayName: get all todos"
  },
  {
    "path": "raml/src/test/resources/path/nested_path_single_entry.raml",
    "content": "#%RAML 1.0\ntitle: test api\n/todo/list:\n  displayName: Todos\n  post:\n    displayName: Create a new todo\n  get:\n      displayName: get all todos"
  },
  {
    "path": "raml/src/test/resources/path/simple_path.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos"
  },
  {
    "path": "raml/src/test/resources/path_parameter/nested_path_parameter.raml",
    "content": "#%RAML 1.0\ntitle: test api\n/todos:\n  displayName: Todos\n  post:\n    displayName: create a new todo\n  /{id}:\n    get:\n        displayName: get todo"
  },
  {
    "path": "raml/src/test/resources/path_parameter/simple_path_parameter.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos/{id}:\n  displayName: Todos\n  get:\n    displayName: Get all todos"
  },
  {
    "path": "raml/src/test/resources/produces/method_declaration_overwrites_default.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nmediaType: [application/json, application/xml]\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          text/plain:\n            type: string"
  },
  {
    "path": "raml/src/test/resources/produces/multiple_default_media_types.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nmediaType: [application/json, application/xml]\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          type: string"
  },
  {
    "path": "raml/src/test/resources/produces/multiple_method_declarations.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          application/json:\n            type: string\n          application/xml:\n            type: string"
  },
  {
    "path": "raml/src/test/resources/produces/no_media_type.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    body:\n      type: string"
  },
  {
    "path": "raml/src/test/resources/produces/single_default_media_type.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\nmediaType: application/json\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          type: string"
  },
  {
    "path": "raml/src/test/resources/produces/single_method_declaration.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    responses:\n      200:\n        body:\n          text/plain:\n            type: string"
  },
  {
    "path": "raml/src/test/resources/query_parameter/query_parameter.raml",
    "content": "#%RAML 1.0\ntitle: test api\nversion: v3\n/todos:\n  displayName: Todos\n  get:\n    displayName: Get all todos\n    queryParameters:\n      tag:\n        displayName: Tag\n        type: string\n        description: Filter todos by a given tag\n        example: Mary Roach\n        required: false\n      limit:\n        displayName: Limit\n        type: number\n        description: Limit results in response\n        example: 25\n        required: true"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'hikaku'\n\ninclude(\n        'core',\n        'openapi',\n        'spring',\n        'wadl',\n        'raml',\n        'jax-rs',\n        'micronaut'\n)"
  },
  {
    "path": "spring/README.md",
    "content": "# hikaku - Spring\n\nSupports Spring MVC 5.3.X.\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md). To check the feature support for this converter.\nYou will find a list of spring specific features that are supported below.\n\n### Paths\n\n+ Supports RequestMapping annotation\n  + _Example:_ `@RequestMapping(\"/todos\")`\n\n+ Supports all HTTP method based mapping annotations (DeleteMapping, GetMapping, PatchMapping, PostMapping, PutMapping)\n  + _Example:_ `@GetMapping(\"/todos\")`\n\n+ Supports endpoint definition on class level, method level and a combination of both.\n\n+ Supports multiple path definitions on all HTTP method based mapping annotations\n  + _Example:_ `@GetMapping(value = [\"/todos\", \"todo/list\"])`\n\n+ Supports multiple path definitions on RequestMapping annotation\n  + _Example:_ `@RequestMapping(value = [\"/todos\", \"todo/list\"], method = [RequestMethod.POST, RequestMethod.GET])`\n\n+ Supports endpoints using regex for path parameter\n  + _Example:_ `@RequestMapping(\"/{id:[0-9]+}\")`\n  \n### HTTP method\n\n+ Supports RequestMapping annotation\n  + _Example:_ `@RequestMapping(method = GET)`\n\n+ Supports all HTTP method based mapping annotations (DeleteMapping, GetMapping, PatchMapping, PostMapping, PutMapping)\n  + _Example:_ `@GetMapping(\"/todos\")`\n\n### Query parameters\n\n+ Supports parameter name using variable name\n  + _Example:_ `@RequestParam tag: String`\n\n+ Supports parameter name defined by 'value'\n  + _Example:_ `@RequestParam(value = \"tag\") otherName: String`\n\n+ Supports parameter name defined by alias 'name'\n  + _Example:_ `@RequestParam(name = \"tag\") otherName: String`\n\n+ Throws an exception in case both 'value' and 'name' are set.\n  + _Example:_ `@RequestParam(value = \"param\", name = \"other\") foo: String`\n\n+ Checks if a parameter is required depending on the value of the 'required' attribute\n  + _Example:_ `@RequestParam(required = false) foo: String`\n\n+ Checks if a parameter is required depending on the existence of the 'defaultValue' attribute\n  + _Example:_ `@RequestParam(value = \"tag\", defaultValue = \"all\")`\n\n### Path parameters\n\n+ Supports parameter name using variable name\n  + _Example:_ `@PathVariable id: Int`\n\n+ Supports parameter name defined by 'value'\n  + _Example:_ `@PathVariable(value = \"id\") otherName: Int`\n\n+ Supports parameter name defined by alias 'name'\n  + _Example:_ `@PathVariable(name = \"id\") otherName: Int`\n\n+ Throws an exception in case both 'value' and 'name' are set.\n  + _Example:_ `@PathVariable(value = \"param\", name = \"other\") foo: Int`\n  \n### Header parameters\n\n+ Supports parameter name using variable name\n  + _Example:_ `@RequestHeader allowCache: String`\n\n+ Supports parameter name defined by 'value'\n  + _Example:_ `@RequestParam(value = \"allow-cache\") otherName: String`\n\n+ Supports parameter name defined by alias 'name'\n  + _Example:_ `@RequestHeader(name = \"allow-cache\") otherName: String`\n\n+ Throws an exception in case both 'value' and 'name' are set.\n  + _Example:_ `@RequestHeader(value = \"param\", name = \"other\") foo: String`\n\n+ Checks if a parameter is required depending on the value of the 'required' attribute\n  + _Example:_ `@RequestHeader(required = false) foo: String`\n\n+ Checks if a parameter is required depending on the existence of the 'defaultValue' attribute\n  + _Example:_ `@RequestHeader(value = \"tracker-id\", defaultValue = \"2394\")`\n\n### Matrix parameters\n\n+ Supports parameter name using variable name\n  + _Example:_ `@MatrixVariable tag: String`\n\n+ Supports parameter name defined by 'value'\n  + _Example:_ `@MatrixVariable(value = \"tag\") otherName: String`\n\n+ Supports parameter name defined by alias 'name'\n  + _Example:_ `@MatrixVariable(name = \"tag\") otherName: String`\n\n+ Throws an exception in case both 'value' and 'name' are set.\n  + _Example:_ `@MatrixVariable(value = \"param\", name = \"other\") foo: String`\n\n+ Checks if a parameter is required depending on the value of the 'required' attribute\n  + _Example:_ `@MatrixVariable(required = false) foo: String`\n\n+ Checks if a parameter is required depending on the existence of the 'defaultValue' attribute\n  + _Example:_ `@MatrixVariable(value = \"tag\", defaultValue = \"shopping\")`\n  \n### Produces\n\n+ Supports RequestMapping annotation\n  + _Example:_ `@RequestMapping(produces = \"text/plain\")`\n\n+ Supports all HTTP method based mapping annotations (DeleteMapping, GetMapping, PatchMapping, PostMapping, PutMapping)\n  + _Example:_ `@GetMapping(produces = \"text/plain\")`\n\n+ Supports `javax.servlet.http.HttpServletResponse` parameter type\n  + _Example:_ `@GetMapping(\"/items\") fun getItems(response: HttpServletResponse)`\n\n+ Supports default value in case no produces definition has been set\n\n+ Supports text/plain if the return value is a String and no produces definition has been set\n\n### Consumes\n\n+ Supports RequestMapping annotation\n  + _Example:_ `@RequestMapping(consumes = \"text/plain\")`\n\n+ Supports all HTTP method based mapping annotations (DeleteMapping, GetMapping, PatchMapping, PostMapping, PutMapping)\n  + _Example:_ `@GetMapping(consumes = \"text/plain\")`\n\n+ Supports default value in case no consumes definition has been set\n\n+ Supports `*/*` if the return value is a String and no consumes definition has been set\n\n## Currently not supported\n\n+ Checking whether or not to explode query parameter.\n  + _Example:_ `@RequestParam(value=\"tag\", required=false) tags: List<String>` **or** `@RequestParam(value=\"tag\", required=false) tags: Array<String>`\n\n+ Query Parameter based on an object\n  + _Example:_ `@GetMapping(\"/todos\") fun getAllTodos(queryParams: MyObject)`\n  \n+ Parameter annotations on a HashMap to dynamically extract parameters\n\n+ Matrix parameters having a binding to a specific path element \n  + _Example:_ `@MatrixVariable(pathVar = \"employee\")`\n  \n+ Produces using negated media type\n  + _Example:_ `@RequestParam(produces = \"!text/plain\")`\n\n+ Consumes using negated media type\n  + _Example:_ `@RequestParam(produces = \"!text/plain\")`\n"
  },
  {
    "path": "spring/build.gradle",
    "content": "buildscript {\n  ext {\n    springBootVersion = '2.5.4'\n  }\n}\n\ngroup = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-spring'\n\ndependencies {\n  api 'org.springframework:spring-webmvc:5.3.9'\n  api project(':core')\n\n  testImplementation \"org.springframework.boot:spring-boot-starter-test:$springBootVersion\"\n  testImplementation \"org.springframework.boot:spring-boot-starter-web:$springBootVersion\"\n}\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-spring'\n        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for spring-mvc implementations.'\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/SpringConverter.kt",
    "content": "package de.codecentric.hikaku.converters.spring\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.AbstractEndpointConverter\nimport de.codecentric.hikaku.converters.spring.extensions.*\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.springframework.context.ApplicationContext\nimport org.springframework.web.method.HandlerMethod\nimport org.springframework.web.servlet.mvc.method.RequestMappingInfo\nimport org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping\n\n/**\n * Extracts and converts [Endpoint]s from a spring [ApplicationContext].\n * @param applicationContext Spring application context\n */\nclass SpringConverter(private val applicationContext: ApplicationContext) : AbstractEndpointConverter() {\n\n    override val supportedFeatures = SupportedFeatures(\n            Feature.QueryParameters,\n            Feature.PathParameters,\n            Feature.HeaderParameters,\n            Feature.MatrixParameters,\n            Feature.Produces,\n            Feature.Consumes,\n            Feature.Deprecation\n    )\n\n    override fun convert(): Set<Endpoint> {\n        return applicationContext.getBean(RequestMappingHandlerMapping::class.java)\n                .handlerMethods\n                .flatMap { mappingEntry ->\n                    mappingEntry.key.paths().flatMap { path ->\n                        createEndpoints(path, mappingEntry)\n                    }\n                }\n                .toSet()\n    }\n\n    private fun createEndpoints(path: String, mappingEntry: Map.Entry<RequestMappingInfo, HandlerMethod>): Set<Endpoint> {\n        val httpMethods = extractAvailableHttpMethods(mappingEntry)\n        val cleanedPath = removeRegex(path)\n\n        val endpoints = httpMethods.map {\n            Endpoint(\n                    path = cleanedPath,\n                    httpMethod = it,\n                    queryParameters = mappingEntry.value.hikakuQueryParameters(),\n                    pathParameters = mappingEntry.value.hikakuPathParameters(),\n                    headerParameters = mappingEntry.value.hikakuHeaderParameters(),\n                    matrixParameters = mappingEntry.value.hikakuMatrixParameters(),\n                    produces = mappingEntry.produces(),\n                    consumes = mappingEntry.consumes(),\n                    deprecated = mappingEntry.isEndpointDeprecated()\n            )\n        }\n        .toMutableSet()\n\n        // Spring always adds an OPTIONS http method if it does not exist, but without query and path parameter\n        if (!httpMethods.contains(OPTIONS)) {\n            endpoints.add(\n                    Endpoint(\n                            path = cleanedPath,\n                            httpMethod = OPTIONS,\n                            deprecated = mappingEntry.isEndpointDeprecated()\n                    )\n            )\n        }\n\n        return endpoints\n    }\n\n    private fun removeRegex(path: String): String {\n        return path.split('/').joinToString(\"/\") { pathSegment ->\n            pathSegment.let {\n                when {\n                    it.contains(':') -> it.replace(Regex(\":.*\"), \"}\")\n                    else -> it\n                }\n            }\n        }\n    }\n\n    private fun extractAvailableHttpMethods(mappingEntry: Map.Entry<RequestMappingInfo, HandlerMethod>): Set<HttpMethod> {\n        val httpMethods = mappingEntry.key.hikakuHttpMethods()\n\n        // Spring adds all http methods except for TRACE if no http method has been set explicitly\n        // OPTIONS is a special case. If it's not added manually it has to be added without any path or query parameters\n        return if (httpMethods.isEmpty()) {\n            HttpMethod.values()\n                    .filterNot { it == TRACE }\n                    .filterNot { it == OPTIONS }\n                    .toSet()\n        } else {\n            // Spring always adds a HEAD http method\n            httpMethods + HEAD\n        }\n    }\n\n    companion object {\n        @JvmField\n        val IGNORE_ERROR_ENDPOINT: (Endpoint) -> Boolean = { endpoint -> endpoint.path == \"/error\" }\n    }\n}\n"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/ConsumesExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport org.springframework.http.MediaType.ALL_VALUE\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport org.springframework.web.bind.annotation.RequestBody\nimport org.springframework.web.method.HandlerMethod\nimport org.springframework.web.servlet.mvc.method.RequestMappingInfo\nimport kotlin.reflect.full.findAnnotation\nimport kotlin.reflect.jvm.jvmErasure\nimport kotlin.reflect.jvm.kotlinFunction\n\ninternal fun Map.Entry<RequestMappingInfo, HandlerMethod>.consumes(): Set<String> {\n    val consumes = this.key\n            .consumesCondition\n            .expressions\n            .map { it.mediaType.toString() }\n            .toSet()\n\n    if (consumes.isNotEmpty()) {\n        return consumes\n    }\n\n    val providesRequestBodyAnnotation = this.value\n            .method\n            .kotlinFunction\n            ?.parameters\n            ?.any {\n                it.findAnnotation<RequestBody>() !== null\n            } ?: false\n\n    if (!providesRequestBodyAnnotation) {\n        return emptySet()\n    }\n\n    val isParameterString = this.value\n            .method\n            .kotlinFunction\n            ?.parameters\n            ?.firstOrNull {\n                it.findAnnotation<RequestBody>() !== null\n            }\n            ?.type\n            ?.jvmErasure\n            ?.let {\n                it.java == java.lang.String::class.java\n            } ?: false\n\n    return if (isParameterString) {\n        setOf(ALL_VALUE)\n    } else {\n        setOf(APPLICATION_JSON_VALUE)\n    }\n}\n"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/DeprecationExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport org.springframework.web.method.HandlerMethod\nimport org.springframework.web.servlet.mvc.method.RequestMappingInfo\n\ninternal fun Map.Entry<RequestMappingInfo, HandlerMethod>.isEndpointDeprecated() =\n        this.value.method.isAnnotationPresent(Deprecated::class.java)\n                || this.value.method.declaringClass.isAnnotationPresent(Deprecated::class.java)"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/HeaderParametersSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport org.springframework.web.bind.annotation.RequestHeader\nimport org.springframework.web.bind.annotation.ValueConstants\nimport org.springframework.web.method.HandlerMethod\nimport kotlin.reflect.KParameter\nimport kotlin.reflect.jvm.kotlinFunction\n\ninternal fun HandlerMethod.hikakuHeaderParameters(): Set<HeaderParameter> {\n    val method = this.method.kotlinFunction ?: return emptySet()\n\n    return method.parameters\n            .filter { it.annotations.filterIsInstance<RequestHeader>().any() }\n            .map { extractHeaderParameter(it) }\n            .toSet()\n}\n\nprivate fun extractHeaderParameter(it: KParameter): HeaderParameter {\n    val requestHeader = it.annotations.find { it is RequestHeader } as RequestHeader\n    val parameterName = extractHeaderParameterName(requestHeader, it)\n    val isRequired = isHeaderParameterRequired(requestHeader)\n\n    return HeaderParameter(parameterName, isRequired)\n}\n\nprivate fun isHeaderParameterRequired(requestHeader: RequestHeader): Boolean {\n    if (requestHeader.defaultValue == ValueConstants.DEFAULT_NONE) {\n        return requestHeader.required\n    }\n\n    return false\n}\n\nprivate fun extractHeaderParameterName(requestHeader: RequestHeader, it: KParameter): String {\n    check(!(requestHeader.value.isNotBlank() && requestHeader.name.isNotBlank())) {\n        \"Both 'value' and 'name' attribute are provided for header parameter '${it.name}'. Only one is permitted.\"\n    }\n\n    return when {\n        requestHeader.value.isNotBlank() -> requestHeader.value\n        requestHeader.name.isNotBlank() -> requestHeader.name\n        else -> it.name ?: \"\"\n    }\n}"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/HttpMethodsSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport de.codecentric.hikaku.endpoints.HttpMethod\nimport org.springframework.web.bind.annotation.RequestMethod\nimport org.springframework.web.servlet.mvc.method.RequestMappingInfo\n\ninternal fun RequestMappingInfo.hikakuHttpMethods(): Set<HttpMethod> {\n    return this.methodsCondition.methods\n            .map {\n                when (it) {\n                    RequestMethod.GET -> HttpMethod.GET\n                    RequestMethod.POST -> HttpMethod.POST\n                    RequestMethod.HEAD -> HttpMethod.HEAD\n                    RequestMethod.PUT -> HttpMethod.PUT\n                    RequestMethod.PATCH -> HttpMethod.PATCH\n                    RequestMethod.DELETE -> HttpMethod.DELETE\n                    RequestMethod.TRACE -> HttpMethod.TRACE\n                    RequestMethod.OPTIONS -> HttpMethod.OPTIONS\n                    null -> HttpMethod.OPTIONS\n                }\n            }\n            .toSet()\n}"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/MatrixParametersSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport de.codecentric.hikaku.endpoints.MatrixParameter\nimport org.springframework.web.bind.annotation.MatrixVariable\nimport org.springframework.web.bind.annotation.ValueConstants\nimport org.springframework.web.method.HandlerMethod\nimport kotlin.reflect.KParameter\nimport kotlin.reflect.jvm.kotlinFunction\n\ninternal fun HandlerMethod.hikakuMatrixParameters(): Set<MatrixParameter> {\n    val method = this.method.kotlinFunction ?: return emptySet()\n\n    return method.parameters\n            .filter { it.annotations.filterIsInstance<MatrixVariable>().any() }\n            .map { extractMatrixParameter(it) }\n            .toSet()\n}\n\nprivate fun extractMatrixParameter(it: KParameter): MatrixParameter {\n    val matrixParameter = it.annotations.find { it is MatrixVariable } as MatrixVariable\n    val parameterName = extractMatrixParameterName(matrixParameter, it)\n    val isRequired = isMatrixParameterRequired(matrixParameter)\n\n    return MatrixParameter(parameterName, isRequired)\n}\n\nprivate fun isMatrixParameterRequired(matrixParameter: MatrixVariable): Boolean {\n    if (matrixParameter.defaultValue == ValueConstants.DEFAULT_NONE) {\n        return matrixParameter.required\n    }\n\n    return false\n}\n\nprivate fun extractMatrixParameterName(matrixParameter: MatrixVariable, it: KParameter): String {\n    check(!(matrixParameter.value.isNotBlank() && matrixParameter.name.isNotBlank())) {\n        \"Both 'value' and 'name' attribute are provided for matrix parameter '${it.name}'. Only one is permitted.\"\n    }\n\n    return when {\n        matrixParameter.value.isNotBlank() -> matrixParameter.value\n        matrixParameter.name.isNotBlank() -> matrixParameter.name\n        else -> it.name ?: \"\"\n    }\n}"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/PathParametersSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.springframework.web.bind.annotation.PathVariable\nimport org.springframework.web.method.HandlerMethod\nimport kotlin.reflect.KParameter\nimport kotlin.reflect.jvm.kotlinFunction\n\ninternal fun HandlerMethod.hikakuPathParameters(): Set<PathParameter> {\n    val method = this.method.kotlinFunction ?: return emptySet()\n\n    return method.parameters\n            .filter { it.annotations.filterIsInstance<PathVariable>().any() }\n            .map { extractPathParameter(it) }\n            .toSet()\n}\n\nprivate fun extractPathParameter(it: KParameter): PathParameter {\n    val requestParam = it.annotations.find { it is PathVariable } as PathVariable\n    val parameterName = extractPathParameterName(requestParam, it)\n\n    return PathParameter(parameterName)\n}\n\nprivate fun extractPathParameterName(requestParam: PathVariable, it: KParameter): String {\n    check(!(requestParam.value.isNotBlank() && requestParam.name.isNotBlank())) {\n        \"Both 'value' and 'name' attribute are provided for path parameter '${it.name}'. Only one is permitted.\"\n    }\n\n    return when {\n        requestParam.value.isNotBlank() -> requestParam.value\n        requestParam.name.isNotBlank() -> requestParam.name\n        else -> it.name ?: \"\"\n    }\n}"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/PathsSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport org.springframework.web.servlet.mvc.method.RequestMappingInfo\n\ninternal fun RequestMappingInfo.paths(): Set<String> {\n    return this.patternsCondition?.patterns ?: emptySet()\n}\n"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/ProducesSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport de.codecentric.hikaku.extensions.isString\nimport de.codecentric.hikaku.extensions.isUnit\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport org.springframework.http.MediaType.TEXT_PLAIN_VALUE\nimport org.springframework.web.bind.annotation.ResponseBody\nimport org.springframework.web.bind.annotation.RestController\nimport org.springframework.web.method.HandlerMethod\nimport org.springframework.web.servlet.mvc.method.RequestMappingInfo\nimport org.springframework.web.servlet.view.RedirectView\nimport java.lang.reflect.Method\nimport kotlin.reflect.full.findAnnotation\nimport kotlin.reflect.full.instanceParameter\nimport kotlin.reflect.jvm.jvmErasure\nimport kotlin.reflect.jvm.kotlinFunction\n\ninternal fun Map.Entry<RequestMappingInfo, HandlerMethod>.produces(): Set<String> {\n    val isNotErrorPath = this.key.patternsCondition?.patterns?.contains(\"/error\") == false\n    val hasNoResponseBodyAnnotation = !this.value.providesResponseBodyAnnotation()\n    val hasNoRestControllerAnnotation = !this.value.providesRestControllerAnnotation()\n    val hasHttpServletResponseParam = this.value.hasHttpServletResponseParam()\n\n    if (isNotErrorPath && (hasNoResponseBodyAnnotation && hasNoRestControllerAnnotation)) {\n        return emptySet()\n    }\n\n    if (isNotErrorPath && (this.value.method.hasNoReturnType() && !hasHttpServletResponseParam)) {\n        return emptySet()\n    }\n\n    val produces = this.key\n            .producesCondition\n            .expressions\n            .map { it.mediaType.toString() }\n            .toSet()\n\n    if (produces.isNotEmpty()) {\n        return produces\n    }\n\n    val returnType = this.value\n            .method\n            .kotlinFunction\n            ?.returnType\n            ?.jvmErasure\n\n    return if (returnType != null) {\n        when {\n            returnType.isString() -> setOf(TEXT_PLAIN_VALUE)\n            returnType.isUnit() -> emptySet()\n            returnType == RedirectView::class -> emptySet()\n            else -> setOf(APPLICATION_JSON_VALUE)\n        }\n    } else {\n        emptySet()\n    }\n}\n\nprivate fun Method.hasNoReturnType() = this.returnType.kotlin.isUnit()\n\nprivate fun HandlerMethod.providesRestControllerAnnotation() = this.method\n        .kotlinFunction\n        ?.instanceParameter\n        ?.type\n        ?.jvmErasure\n        ?.findAnnotation<RestController>() != null\n\nprivate fun HandlerMethod.providesResponseBodyAnnotation() = isResponseBodyAnnotationOnClass() || isResponseBodyAnnotationOnFunction()\n\nprivate fun HandlerMethod.isResponseBodyAnnotationOnClass() = this.method\n        .kotlinFunction\n        ?.instanceParameter\n        ?.type\n        ?.jvmErasure\n        ?.findAnnotation<ResponseBody>() != null\n\nprivate fun HandlerMethod.isResponseBodyAnnotationOnFunction() = this.method\n        .kotlinFunction\n        ?.findAnnotation<ResponseBody>() != null\n\nprivate fun HandlerMethod.hasHttpServletResponseParam(): Boolean {\n    return this.methodParameters\n        .any { it.parameterType.name == \"javax.servlet.http.HttpServletResponse\" }\n}\n"
  },
  {
    "path": "spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/QueryParametersSpringExtension.kt",
    "content": "package de.codecentric.hikaku.converters.spring.extensions\n\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.springframework.web.bind.annotation.RequestParam\nimport org.springframework.web.bind.annotation.ValueConstants\nimport org.springframework.web.method.HandlerMethod\nimport kotlin.reflect.KParameter\nimport kotlin.reflect.jvm.kotlinFunction\n\ninternal fun HandlerMethod.hikakuQueryParameters(): Set<QueryParameter> {\n    val method = this.method.kotlinFunction ?: return emptySet()\n\n    return method.parameters\n            .filter { it.annotations.filterIsInstance<RequestParam>().any() }\n            .map { extractQueryParameter(it) }\n            .toSet()\n}\n\nprivate fun extractQueryParameter(it: KParameter): QueryParameter {\n    val requestParam = it.annotations.find { it is RequestParam } as RequestParam\n    val parameterName = extractQueryParameterName(requestParam, it)\n    val isRequired = isQueryParameterRequired(requestParam)\n\n    return QueryParameter(parameterName, isRequired)\n}\n\nprivate fun isQueryParameterRequired(requestParam: RequestParam): Boolean {\n    if (requestParam.defaultValue == ValueConstants.DEFAULT_NONE) {\n        return requestParam.required\n    }\n\n    return false\n}\n\nprivate fun extractQueryParameterName(requestParam: RequestParam, it: KParameter): String {\n    check(!(requestParam.value.isNotBlank() && requestParam.name.isNotBlank())) {\n        \"Both 'value' and 'name' attribute are provided for query parameter '${it.name}'. Only one is permitted.\"\n    }\n\n    return when {\n        requestParam.value.isNotBlank() -> requestParam.value\n        requestParam.name.isNotBlank() -> requestParam.name\n        else -> it.name ?: \"\"\n    }\n}"
  },
  {
    "path": "spring/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/consumes/ConsumesTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.consumes\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.http.MediaType.*\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.*\nimport org.springframework.web.multipart.MultipartFile\n\n@SpringBootApplication\nopen class DummyApp\n\ndata class Todo(val description: String)\ndata class Tag(val name: String)\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOneMediaTypeIsInheritedByAllFunctionsController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n\n    @RequestMapping(\"/tags\")\n    fun tags(@RequestBody tag: Tag) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n\n    @RequestMapping(\"/tags\")\n    fun tags(@RequestBody tag: Tag) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @RequestMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingMultipartFormIsExtractedCorrectlyController {\n\n    @RequestMapping(\n            path = [\"/form\"],\n            method = [RequestMethod.POST],\n            consumes = [MULTIPART_FORM_DATA_VALUE]\n    )\n    fun form(\n            @RequestPart(\"title\") title: String,\n            @RequestPart(\"file\") form: MultipartFile\n    ) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @RequestMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n\n    @RequestMapping(\"/tags\", consumes = [TEXT_PLAIN_VALUE])\n    fun tags(@RequestBody tag: Tag) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n\n    @RequestMapping(\"/tags\", consumes = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun tags(@RequestBody tag: Tag) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnClassDefaultValueController {\n\n    @RequestMapping\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnFunctionDefaultValueController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnClassWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @RequestMapping\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnFunctionWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnClassWithoutRequestBodyAnnotationController {\n\n    @RequestMapping\n    fun todos(todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnFunctionWithoutConsumesAnnotationController {\n\n    @RequestMapping(\"/todos\")\n    fun todos(todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @GetMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @GetMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingDefaultValueController {\n\n    @GetMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @GetMapping(\"/todos\")\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingWithoutRequestBodyAnnotationController {\n\n    @GetMapping(\"/todos\")\n    fun todos(todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @DeleteMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @DeleteMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingDefaultValueController {\n\n    @DeleteMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @DeleteMapping(\"/todos\")\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingWithoutRequestBodyAnnotationController {\n\n    @DeleteMapping(\"/todos\")\n    fun todos(todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PatchMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PatchMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingDefaultValueController {\n\n    @PatchMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @PatchMapping(\"/todos\")\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingWithoutRequestBodyAnnotationController {\n\n    @PatchMapping(\"/todos\")\n    fun todos(todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PostMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PostMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingDefaultValueController {\n\n    @PostMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @PostMapping(\"/todos\")\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingWithoutRequestBodyAnnotationController {\n\n    @PostMapping(\"/todos\")\n    fun todos(todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PutMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PutMapping(\"/todos\", consumes = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingDefaultValueController {\n\n    @PutMapping(\"/todos\")\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingWithoutConsumesInfoAndStringAsRequestBodyValueController {\n\n    @PutMapping(\"/todos\")\n    fun todos(@RequestBody todo: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingWithoutRequestBodyAnnotationController {\n\n    @PutMapping(\"/todos\")\n    fun todos(todo: String) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingOneMediaTypeIsOverwrittenController {\n\n    @GetMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingOneMediaTypeIsOverwrittenController {\n\n    @DeleteMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingOneMediaTypeIsOverwrittenController {\n\n    @PatchMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingOneMediaTypeIsOverwrittenController {\n\n    @PostMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingOneMediaTypeIsOverwrittenController {\n\n    @PutMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingMultipleMediaTypesAreOverwrittenController {\n\n    @GetMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingMultipleMediaTypesAreOverwrittenController {\n\n    @DeleteMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PatchMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PostMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@RequestMapping(consumes = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PutMapping(\"/todos\", consumes = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class ErrorEndpointController {\n\n    @GetMapping(\"/todos\", consumes = [APPLICATION_PDF_VALUE])\n    fun todos(@RequestBody todo: Todo) { }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/consumes/SpringConverterConsumesTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.consumes\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.*\n\nclass SpringConverterConsumesTest {\n\n    @Nested\n    inner class RequestMappingAnnotationTests {\n\n        @Nested\n        inner class ClassLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class OneMediaTypeIsInheritedByAllFunctionsTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `media type declared at class level using RequestMapping annotation is inherited by all functions`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/tags\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleMediaTypesAreInheritedByAllFunctionsTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple media types declared at class level using RequestMapping annotation are inherited by all functions`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/tags\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/tags\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefaultValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared at class level will fallback to default media type`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassWithoutRequestBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoRequestBodyAnnotationTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no RequestBody annotation results in an empty produces list`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n\n        @Nested\n        inner class FunctionLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `media type declared at function level using RequestMapping annotation is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipartFormIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipartFormIsExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multipart form media type is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/form\",\n                                    httpMethod = POST,\n                                    consumes = setOf(MULTIPART_FORM_DATA_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/form\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(MULTIPART_FORM_DATA_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/form\",\n                                    httpMethod = OPTIONS,\n                            ),\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple media types declared at function level using RequestMapping annotation are extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefaultValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared at function level will fallback to default media type`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    consumes = setOf(ALL_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionWithoutConsumesAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class EmptyAnnotationTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no RequestBody nor consumes annotation results in an empty produces list`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class GetMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(GetMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using GetMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using GetMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingWithoutRequestBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoRequestBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no RequestBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class DeleteMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(DeleteMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using DeleteMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using DeleteMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingWithoutRequestBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoRequestBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no RequestBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PatchMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PatchMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PatchMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PatchMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingWithoutRequestBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoRequestBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no RequestBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PostMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PostMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PostMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PostMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingWithoutRequestBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoRequestBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no RequestBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PutMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PutMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PutMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PutMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingWithoutConsumesInfoAndStringAsRequestBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to accept all`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(ALL_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingWithoutRequestBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoRequestBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no RequestBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class OverwriteTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by a declaration at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = GET,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = POST,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = PUT,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = PATCH,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = DELETE,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/tags\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by a declaration at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = GET,\n                                consumes = setOf(APPLICATION_PDF_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = POST,\n                                consumes = setOf(APPLICATION_PDF_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = HEAD,\n                                consumes = setOf(APPLICATION_PDF_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = PUT,\n                                consumes = setOf(APPLICATION_PDF_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = PATCH,\n                                consumes = setOf(APPLICATION_PDF_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/tags\",\n                                httpMethod = DELETE,\n                                consumes = setOf(APPLICATION_PDF_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/tags\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by GetMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by DeleteMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PatchMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PostMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PutMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by GetMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by DeleteMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PatchMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PostMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PutMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                consumes = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(ErrorEndpointController::class)\n    inner class MediaTypeIsNotAddedToDefaultErrorEndpoint {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `error endpoint does not provide the same media type`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            consumes = setOf(APPLICATION_PDF_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            consumes = setOf(APPLICATION_PDF_VALUE)\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/deprecation/DeprecationTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.deprecation\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.web.bind.annotation.GetMapping\nimport org.springframework.web.bind.annotation.RestController\n\n@SpringBootApplication\nopen class DummyApp\n\ndata class Todo(val description: String = \"\")\n\n@RestController\nopen class NoDeprecationController {\n\n    @GetMapping(\"/todos\")\n    fun todos() = Todo()\n}\n\n@RestController\n@Deprecated(\"Test\")\nopen class DeprecatedClassController {\n\n    @GetMapping(\"/todos\")\n    fun todos() = Todo()\n}\n\n@RestController\nopen class DeprecatedFunctionController {\n\n    @GetMapping(\"/todos\")\n    @Deprecated(\"Test\")\n    fun todos() = Todo()\n}"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/deprecation/SpringConverterDeprecationTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.deprecation\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\n\nclass SpringConverterDeprecationTest {\n\n    @Nested\n    @WebMvcTest(NoDeprecationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class NoDeprecationTest {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `no deprecation`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE),\n                            deprecated = false\n                    ),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE),\n                            deprecated = false\n                    ),\n                    Endpoint(\"/todos\", OPTIONS, deprecated = false)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(DeprecatedClassController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class NoDeprecatedClassTest {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `deprecated class`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE),\n                            deprecated = true\n                    ),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE),\n                            deprecated = true\n                    ),\n                    Endpoint(\"/todos\", OPTIONS, deprecated = true)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(DeprecatedFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class NoDeprecatedFunctionTest {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `deprcated function`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE),\n                            deprecated = true\n                    ),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE),\n                            deprecated = true\n                    ),\n                    Endpoint(\"/todos\", OPTIONS, deprecated = true)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/headerparameters/HeaderParameterTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.headerparameters\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.GetMapping\nimport org.springframework.web.bind.annotation.RequestHeader\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterNamedByVariableController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader allowCache: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterNamedByValueAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader(value = \"allow-cache\") variable: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterNamedByNameAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader(name = \"allow-cache\") variable: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterHavingBothNameAndValueAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader(value=\"valueAttribute\", name = \"nameAttribute\") variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterOptionalController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader(name = \"allow-cache\", required = false) variable: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterOptionalBecauseOfDefaultValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader(name = \"tracker-id\", defaultValue = \"unknown\") variable: Boolean) { }\n}\n\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class HeaderParameterOnDefaultErrorEndpointController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestHeader(value = \"allow-cache\") variable: Boolean) { }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/headerparameters/SpringConverterHeaderParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.headerparameters\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport org.springframework.http.MediaType.TEXT_HTML_VALUE\nimport kotlin.test.assertFailsWith\n\nclass SpringConverterHeaderParameterTest {\n\n    @Nested\n    @WebMvcTest(HeaderParameterNamedByVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class HeaderParameterNamedByVariableTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `header parameter name defined by variable name`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                            HeaderParameter(\"allowCache\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        headerParameters = setOf(\n                                HeaderParameter(\"allowCache\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(HeaderParameterNamedByValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class HeaderParameterNamedByValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `header parameter name defined by attribute 'value'`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                            HeaderParameter(\"allow-cache\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        headerParameters = setOf(\n                            HeaderParameter(\"allow-cache\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(HeaderParameterNamedByNameAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class HeaderParameterNamedByNameAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `header parameter name defined by attribute 'name'`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                            HeaderParameter(\"allow-cache\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        headerParameters = setOf(\n                            HeaderParameter(\"allow-cache\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(HeaderParameterHavingBothNameAndValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class HeaderParameterHavingBothNameAndValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `both 'value' and 'name' attribute defined for header parameter`() {\n            assertFailsWith<IllegalStateException> {\n                SpringConverter(context).conversionResult\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(HeaderParameterOptionalController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class HeaderParameterOptionalTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `header parameter optional`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            headerParameters = setOf(\n                                HeaderParameter(\"allow-cache\", false)\n                            )\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            headerParameters = setOf(\n                                HeaderParameter(\"allow-cache\", false)\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(HeaderParameterOptionalBecauseOfDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class HeaderParameterOptionalBecauseOfDefaultValueTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `header parameter optional because of a default value`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        headerParameters = setOf(\n                            HeaderParameter(\"tracker-id\", false)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        headerParameters = setOf(\n                            HeaderParameter(\"tracker-id\", false)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n\n    @Nested\n    @WebMvcTest(HeaderParameterOnDefaultErrorEndpointController::class)\n    inner class HeaderParameterOnDefaultErrorEndpointTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `header parameter is not available in default error endpoints`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            headerParameters = setOf(\n                                    HeaderParameter(\"allow-cache\", true)\n                            )\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            headerParameters = setOf(\n                                    HeaderParameter(\"allow-cache\", true)\n                            )\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/httpmethod/HttpMethodTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.httpmethod\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.*\nimport org.springframework.web.bind.annotation.RequestMethod.*\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\n@RequestMapping(\"/todos\", method = [GET])\nopen class RequestMappingDefinedOnClassWithExplicitGetMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitGetMethodController {\n\n    @RequestMapping(\"/todos\", method = [GET])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [POST])\nopen class RequestMappingDefinedOnClassWithExplicitPostMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitPostMethodController {\n\n    @RequestMapping(\"/todos\", method = [POST])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [HEAD])\nopen class RequestMappingDefinedOnClassWithExplicitHeadMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitHeadMethodController {\n\n    @RequestMapping(\"/todos\", method = [HEAD])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [PUT])\nopen class RequestMappingDefinedOnClassWithExplicitPutMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitPutMethodController {\n\n    @RequestMapping(\"/todos\", method = [PUT])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [PATCH])\nopen class RequestMappingDefinedOnClassWithExplicitPatchMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitPatchMethodController {\n\n    @RequestMapping(\"/todos\", method = [PATCH])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [DELETE])\nopen class RequestMappingDefinedOnClassWithExplicitDeleteMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitDeleteMethodController {\n\n    @RequestMapping(\"/todos\", method = [DELETE])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [TRACE])\nopen class RequestMappingDefinedOnClassWithExplicitTraceMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitTraceMethodController {\n\n    @RequestMapping(\"/todos\", method = [TRACE])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [OPTIONS])\nopen class RequestMappingDefinedOnClassWithExplicitOptionsMethodController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionWithExplicitOptionsMethodController {\n\n    @RequestMapping(\"/todos\", method = [OPTIONS])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class RequestMappingDefinedOnClassNoHttpMethodDefinedController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\nopen class RequestMappingDefinedOnFunctionNoHttpMethodDefinedController {\n\n    @RequestMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [PUT])\nopen class RequestMappingDefinedOnClassAndFunctionWithDifferentHttpMethodsController {\n\n    @RequestMapping(method = [PATCH])\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [GET])\nopen class RequestMappingDefinedOnClassAndFunctionWithDifferentHttpMethodsAndDifferentPathsController {\n\n    @RequestMapping(\"/{id}\", method = [PUT])\n    fun todo() { }\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [PUT, PATCH, TRACE])\nopen class RequestMappingDefinedOnClassWithMultipleMethodsController {\n\n    @RequestMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [PUT, PATCH, TRACE])\nopen class RequestMappingDefinedOnFunctionWithMultipleMethodsController {\n\n    @RequestMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [POST])\nopen class RequestMappingWithPostAndGetMappingInCombinationController {\n\n    @GetMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [POST])\nopen class RequestMappingWithPostAndDeleteMappingInCombinationController {\n\n    @DeleteMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [POST])\nopen class RequestMappingWithPostAndPatchMappingInCombinationController {\n\n    @PatchMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [TRACE])\nopen class RequestMappingWithTraceAndPostMappingInCombinationController {\n\n    @PostMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [POST])\nopen class RequestMappingWithPostAndPutMappingInCombinationController {\n\n    @PutMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class EmptyRequestMappingAndGetMappingInCombinationController {\n\n    @GetMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class EmptyRequestMappingAndDeleteMappingInCombinationController {\n\n    @DeleteMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class EmptyRequestMappingAndPatchMappingInCombinationController {\n\n    @PatchMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class EmptyRequestMappingAndPostMappingInCombinationController {\n\n    @PostMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class EmptyRequestMappingAndPutMappingInCombinationController {\n\n    @PutMapping\n    fun todo() { }\n}\n\n@Controller\nopen class RequestMappingFirstAndGetMappingBothOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    @GetMapping\n    fun todo() { }\n}\n\n@Controller\nopen class GetMappingFirstAndRequestMappingBothOnFunctionController {\n\n    @GetMapping\n    @RequestMapping(\"/todos\")\n    fun todo() { }\n}\n\n@Controller\nopen class RequestMappingFirstAndDeleteMappingBothOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    @DeleteMapping\n    fun todo() { }\n}\n\n@Controller\nopen class DeleteMappingFirstAndRequestMappingBothOnFunctionController {\n\n    @DeleteMapping\n    @RequestMapping(\"/todos\")\n    fun todo() { }\n}\n\n@Controller\nopen class RequestMappingFirstAndPatchMappingBothOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    @PatchMapping\n    fun todo() { }\n}\n\n@Controller\nopen class PatchMappingFirstAndRequestMappingBothOnFunctionController {\n\n    @PatchMapping\n    @RequestMapping(\"/todos\")\n    fun todo() { }\n}\n\n@Controller\nopen class RequestMappingFirstAndPostMappingBothOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    @PostMapping\n    fun todo() { }\n}\n\n@Controller\nopen class PostMappingFirstAndRequestMappingBothOnFunctionController {\n\n    @PostMapping\n    @RequestMapping(\"/todos\")\n    fun todo() { }\n}\n\n@Controller\nopen class RequestMappingFirstAndPutMappingBothOnFunctionController {\n\n    @RequestMapping(\"/todos\")\n    @PutMapping\n    fun todo() { }\n}\n\n@Controller\nopen class PutMappingFirstAndRequestMappingBothOnFunctionController {\n\n    @PutMapping\n    @RequestMapping(\"/todos\")\n    fun todo() { }\n}\n\n@Controller\nopen class GetMappingController {\n\n    @GetMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\nopen class DeleteMappingController {\n\n    @DeleteMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\nopen class PatchMappingController {\n\n    @PatchMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\nopen class PostMappingController {\n\n    @PostMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\nopen class PutMappingController {\n\n    @PutMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\nopen class MultipleHttpMethodMappingAnnotationsController {\n\n    @GetMapping(\"/todos\")\n    @PostMapping(\"/todos\")\n    @DeleteMapping(\"/todos\")\n    fun tdos() { }\n}\n\n@Controller\nopen class HttpMethodsForDefaultErrorEndpointController {\n\n    @GetMapping(\"/todos\")\n    fun todos() { }\n}"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/httpmethod/SpringConverterHttpMethodTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.httpmethod\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport org.springframework.http.MediaType.TEXT_HTML_VALUE\n\nclass HttpMethodTestController {\n\n    @Nested\n    inner class RequestMappingTests {\n\n        @Nested\n        inner class ClassLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitGetMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitGetMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit GET method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitPostMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitPostMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit POST method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitHeadMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitHeadMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit HEAD method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitPutMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitPutMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit PUT method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitPatchMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitPatchMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit PATCH method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitDeleteMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitDeleteMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit DELETE method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitTraceMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitTraceMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit TRACE method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", TRACE),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithExplicitOptionsMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithExplicitOptionsMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit OPTIONS method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassNoHttpMethodDefinedController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoHttpMethodDefinedTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no http method defined means that spring supports all http methods except for trace`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnClassWithMultipleMethodsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithMultipleMethodsTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint providing multiple http methods`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", TRACE),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n        }\n\n        @Nested\n        inner class FunctionLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitGetMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitGetMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit GET method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitPostMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitPostMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit POST method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitHeadMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitHeadMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit HEAD method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitPutMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitPutMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit PUT method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitPatchMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitPatchMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit PATCH method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitDeleteMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitDeleteMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit DELETE method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitTraceMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitTraceMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit TRACE method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", TRACE),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithExplicitOptionsMethodController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionWithExplicitOptionsMethodTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint defined on class having explicit OPTIONS method definition is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionNoHttpMethodDefinedController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoHttpMethodDefinedTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no http method defined means that spring supports all http methods except for trace`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingDefinedOnFunctionWithMultipleMethodsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassWithMultipleMethodsTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint providing multiple http methods`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", TRACE),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class HttpMethodMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(GetMappingController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingControllerTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint defined on function using GetMapping anbnotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingControllerTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint defined on function using DeleteMapping anbnotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingControllerTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint defined on function using PatchMapping anbnotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingControllerTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint defined on function using PostMapping anbnotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingControllerTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint defined on function using PutMapping anbnotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        inner class HttpMethodMappingAnnotationTests {\n\n            @Nested\n            @WebMvcTest(MultipleHttpMethodMappingAnnotationsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleHttpMethodMappingAnnotationsTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple HttpMethodMapping annotations are not supported by spring - most outer annotation wins`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class ConjunctionTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingDefinedOnClassAndFunctionWithDifferentHttpMethodsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnClassAndFunctionWithDifferentHttpMethodsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `No overwrite for RequestMapping defined on class and function for the same path with different http methods - instead both http methods will be supported`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingDefinedOnClassAndFunctionWithDifferentHttpMethodsAndDifferentPathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnClassAndFunctionWithDifferentHttpMethodsAndDifferentPathsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping defined on class and function for the different paths with different http methods will create two endpoints with combined http methods for the nested path`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos/{id}\", GET),\n                        Endpoint(\"/todos/{id}\", PUT),\n                        Endpoint(\"/todos/{id}\", OPTIONS),\n                        Endpoint(\"/todos/{id}\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingWithPostAndGetMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingWithPostAndGetMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping providing POST defined on class and GetMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingWithPostAndDeleteMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingWithPostAndDeleteMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping providing POST defined on class and DeleteMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingWithPostAndPatchMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingWithPostAndPatchMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping providing POST defined on class and PatchMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingWithTraceAndPostMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingWithTraceAndPostMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping providing TRACE defined on class and PostMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", TRACE),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingWithPostAndPutMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingWithPostAndPutMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping providing POST defined on class and PutMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(EmptyRequestMappingAndGetMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class EmptyRequestMappingAndGetMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping without http method defined on class and GetMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(EmptyRequestMappingAndDeleteMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class EmptyRequestMappingAndDeleteMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping without http method defined on class and DeleteMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(EmptyRequestMappingAndPatchMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class EmptyRequestMappingAndPatchMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping without http method defined on class and PatchMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(EmptyRequestMappingAndPostMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class EmptyRequestMappingAndPostMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping without http method defined on class and PostMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(EmptyRequestMappingAndPutMappingInCombinationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class EmptyRequestMappingAndPutMappingInCombinationTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping without http method defined on class and PutMapping on function`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class OverwriteTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingFirstAndGetMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingFirstAndGetMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and GetMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingFirstAndRequestMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingFirstAndRequestMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and GetMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingFirstAndDeleteMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingFirstAndDeleteMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and DeleteMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingFirstAndRequestMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingFirstAndRequestMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and DeleteMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingFirstAndPatchMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingFirstAndPatchMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and PatchMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingFirstAndRequestMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingFirstAndRequestMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and PatchMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingFirstAndPostMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingFirstAndPostMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and PostMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingFirstAndRequestMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingFirstAndRequestMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and PostMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingFirstAndPutMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingFirstAndPutMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and PutMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingFirstAndRequestMappingBothOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingFirstAndRequestMappingBothOnFunctionTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `RequestMapping and PutMapping both on function, but behaves like RequestMapping without http methods`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(HttpMethodsForDefaultErrorEndpointController::class)\n    inner class HttpMethodsForDefaultErrorEndpointTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `all http methods are provided by the default error endpoint`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\"/todos\", GET),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\"/todos\", HEAD),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/matrixparameters/MatrixParameterTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.matrixparameters\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.GetMapping\nimport org.springframework.web.bind.annotation.MatrixVariable\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterNamedByVariableController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable tag: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterNamedByValueAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable(value = \"tag\") variable: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterNamedByNameAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable(name = \"tag\") variable: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterHavingBothNameAndValueAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable(value=\"valueAttribute\", name = \"nameAttribute\") variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterOptionalController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable(name = \"tag\", required = false) variable: Boolean) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterOptionalBecauseOfDefaultValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable(name = \"tag\", defaultValue = \"unknown\") variable: Boolean) { }\n}\n\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class MatrixParameterOnDefaultErrorEndpointController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@MatrixVariable(value = \"tag\") variable: Boolean) { }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/matrixparameters/SpringConverterMatrixParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.matrixparameters\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport de.codecentric.hikaku.endpoints.MatrixParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport org.springframework.http.MediaType.TEXT_HTML_VALUE\nimport kotlin.test.assertFailsWith\n\nclass SpringConverterMatrixParameterTest {\n\n    @Nested\n    @WebMvcTest(MatrixParameterNamedByVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class MatrixParameterNamedByVariableTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `matrix parameter name defined by variable name`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        matrixParameters = setOf(\n                                MatrixParameter(\"tag\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(MatrixParameterNamedByValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class MatrixParameterNamedByValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `matrix parameter name defined by attribute 'value'`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(MatrixParameterNamedByNameAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class MatrixParameterNamedByNameAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `matrix parameter name defined by attribute 'name'`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(MatrixParameterHavingBothNameAndValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class MatrixParameterHavingBothNameAndValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `both 'value' and 'name' attribute defined for matrix parameter`() {\n            assertFailsWith<IllegalStateException> {\n                SpringConverter(context).conversionResult\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(MatrixParameterOptionalController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class MatrixParameterOptionalTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `matrix parameter optional`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            matrixParameters = setOf(\n                                MatrixParameter(\"tag\", false)\n                            )\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            matrixParameters = setOf(\n                                MatrixParameter(\"tag\", false)\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(MatrixParameterOptionalBecauseOfDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class MatrixParameterOptionalBecauseOfDefaultValueTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `matrix parameter optional because of a default value`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", false)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        matrixParameters = setOf(\n                            MatrixParameter(\"tag\", false)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n\n    @Nested\n    @WebMvcTest(MatrixParameterOnDefaultErrorEndpointController::class)\n    inner class MatrixParameterOnDefaultErrorEndpointTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `matrix parameter is not available in default error endpoints`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            matrixParameters = setOf(\n                                    MatrixParameter(\"tag\", true)\n                            )\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            matrixParameters = setOf(\n                                    MatrixParameter(\"tag\", true)\n                            )\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/path/PathTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.path\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.*\nimport org.springframework.web.bind.annotation.RequestMethod.GET\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\n@RequestMapping(\"/todos\", \"/todo/list\", method = [GET])\nopen class RequestMappingOnClassWithMultiplePathsController {\n\n    @RequestMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos\", method = [GET])\nopen class RequestMappingIgnoreErrorPathController {\n\n    @RequestMapping\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todos/{id:[0-9]+}\", method = [GET])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnClassProvidingRegexForPathVariableController {\n\n    @RequestMapping\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\n@RequestMapping(\"/todos/{id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}\", method = [GET])\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnClassProvidingComplexRegexForPathVariableController {\n\n    @RequestMapping\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnClassProvidingMultipleRegexForPathVariableController {\n\n    @RequestMapping(\"/todos/{id:[0-9]+}/{title:[a-z]*}\", method = [GET])\n    fun todo(@PathVariable(name = \"id\",) variable: Int, @PathVariable(name = \"title\") title: String) { }\n}\n\n@Controller\nopen class RequestMappingOnFunctionWithMultiplePathsController {\n\n    @RequestMapping(\"/todos\", \"/todo/list\", method = [GET])\n    fun todo() { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnFunctionProvidingRegexForPathVariableController {\n\n    @RequestMapping(\"/todos/{id:[0-9]+}\", method = [GET])\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnFunctionProvidingComplexRegexForPathVariableController {\n\n    @RequestMapping(\"/todos/{id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}\", method = [GET])\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class RequestMappingOnFunctionProvidingMultipleRegexForPathVariableController {\n\n    @RequestMapping(\"/todos/{id:[0-9]+}/{title:[a-z]*}\", method = [GET])\n    fun todo(@PathVariable(name = \"id\") variable: Int, @PathVariable(name = \"title\") title: String) { }\n}\n\n@Controller\nopen class GetMappingOnFunctionWithMultiplePathsController {\n\n    @GetMapping(\"/todos\", \"/todo/list\")\n    fun todo() { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class GetMappingProvidingRegexForPathVariableController {\n\n    @GetMapping(\"/todos/{id:[0-9]+}\")\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\nopen class DeleteMappingOnFunctionWithMultiplePathsController {\n\n    @DeleteMapping(\"/todos\", \"/todo/list\")\n    fun todo() { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class DeleteMappingProvidingRegexForPathVariableController {\n\n    @DeleteMapping(\"/todos/{id:[0-9]+}\")\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\nopen class PatchMappingOnFunctionWithMultiplePathsController {\n\n    @PatchMapping(\"/todos\", \"/todo/list\")\n    fun todo() { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PatchMappingProvidingRegexForPathVariableController {\n\n    @PatchMapping(\"/todos/{id:[0-9]+}\")\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\nopen class PostMappingOnFunctionWithMultiplePathsController {\n\n    @PostMapping(\"/todos\", \"/todo/list\")\n    fun todo() { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PostMappingProvidingRegexForPathVariableController {\n\n    @PostMapping(\"/todos/{id:[0-9]+}\")\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\nopen class PutMappingOnFunctionWithMultiplePathsController {\n\n    @PutMapping(\"/todos\", \"/todo/list\")\n    fun todo() { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PutMappingProvidingRegexForPathVariableController {\n\n    @PutMapping(\"/todos/{id:[0-9]+}\")\n    fun todo(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\n@RequestMapping(\"/todo\", method = [GET])\nopen class RequestMappingNestedPathController {\n\n    @RequestMapping(\"/list\")\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todo\")\nopen class GetMappingNestedPathController {\n\n    @GetMapping(\"/list\")\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todo\")\nopen class DeleteMappingNestedPathController {\n\n    @DeleteMapping(\"/list\")\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todo\")\nopen class PatchMappingNestedPathController {\n\n    @PatchMapping(\"/list\")\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todo\")\nopen class PostMappingNestedPathController {\n\n    @PostMapping(\"/list\")\n    fun todo() { }\n}\n\n@Controller\n@RequestMapping(\"/todo\")\nopen class PutMappingNestedPathController {\n\n    @PutMapping(\"/list\")\n    fun todo() { }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/path/SpringConverterPathTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.path\n\nimport de.codecentric.hikaku.Hikaku\nimport de.codecentric.hikaku.HikakuConfig\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.converters.EndpointConverter\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.converters.spring.SpringConverter.Companion.IGNORE_ERROR_ENDPOINT\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\n\nclass SpringConverterPathTest {\n\n    @Nested\n    inner class RequestMappingTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingIgnoreErrorPathController::class)\n        inner class RequestMappingIgnoreErrorPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `pre defined filter for ignoring error paths`() {\n                //given\n                val specification = object : EndpointConverter {\n                    override val conversionResult = setOf(\n                        Endpoint(httpMethod = GET, path = \"/todos\"),\n                        Endpoint(httpMethod = HEAD, path = \"/todos\"),\n                        Endpoint(httpMethod = OPTIONS, path = \"/todos\")\n                    )\n                    override val supportedFeatures = SupportedFeatures()\n                }\n\n                val hikakuConfig = HikakuConfig(filters = listOf(IGNORE_ERROR_ENDPOINT))\n                val implementation = SpringConverter(context)\n\n                //when\n                val hikaku = Hikaku(config = hikakuConfig, specification = specification, implementation = implementation)\n\n                //then\n                hikaku.match()\n            }\n        }\n\n        @Nested\n        inner class ClassLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnClassWithMultiplePathsTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple paths extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todo/list\", GET),\n                            Endpoint(\"/todo/list\", OPTIONS),\n                            Endpoint(\"/todo/list\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnClassProvidingRegexForPathVariableTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint having regex on path parameter using RequestMapping converts to a path without the regex`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"id\")\n                                    )\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = HEAD,\n                                    pathParameters = setOf(\n                                            PathParameter(\"id\")\n                                    )\n                            ),\n                            Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassProvidingComplexRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnClassProvidingComplexRegexForPathVariableTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint having complex regex on path parameter using RequestMapping converts to a path without the regex`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                PathParameter(\"id\")\n                            )\n                        ),\n                        Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                PathParameter(\"id\")\n                            )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassProvidingMultipleRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnClassProvidingMutlipleRegexForPathVariableTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint having complex regex on path parameter using RequestMapping converts to a path without the regex`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                            path = \"/todos/{id}/{title}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                PathParameter(\"id\"),\n                                PathParameter(\"title\"),\n                            )\n                        ),\n                        Endpoint(\n                            path = \"/todos/{id}/{title}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                PathParameter(\"id\"),\n                                PathParameter(\"title\"),\n                            )\n                        ),\n                        Endpoint(\"/todos/{id}/{title}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n\n        @Nested\n        inner class FunctionLevelTest {\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnFunctionWithMultiplePathsTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple paths extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todo/list\", GET),\n                            Endpoint(\"/todo/list\", OPTIONS),\n                            Endpoint(\"/todo/list\", HEAD)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnFunctionProvidingRegexForPathVariableTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint having regex on path parameter using RequestMapping converts to a path without the regex`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    pathParameters = setOf(\n                                            PathParameter(\"id\")\n                                    )\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = HEAD,\n                                    pathParameters = setOf(\n                                            PathParameter(\"id\")\n                                    )\n                            ),\n                            Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionProvidingComplexRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnFunctionProvidingComplexRegexForPathVariableTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint having complex regex on path parameter using RequestMapping converts to a path without the regex`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                PathParameter(\"id\")\n                            )\n                        ),\n                        Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                PathParameter(\"id\")\n                            )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionProvidingMultipleRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class RequestMappingOnFunctionProvidingMutlipleRegexForPathVariableTest {\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `endpoint having complex regex on path parameter using RequestMapping converts to a path without the regex`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                            path = \"/todos/{id}/{title}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                PathParameter(\"id\"),\n                                PathParameter(\"title\"),\n                            )\n                        ),\n                        Endpoint(\n                            path = \"/todos/{id}/{title}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                PathParameter(\"id\"),\n                                PathParameter(\"title\"),\n                            )\n                        ),\n                        Endpoint(\"/todos/{id}/{title}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class HttpMethodMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(GetMappingOnFunctionWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingOnFunctionWithMultiplePathsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todo/list\", GET),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingProvidingRegexForPathVariableTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint having regex on path parameter using converts to a path without the regex`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = GET,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        )\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingOnFunctionWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingOnFunctionWithMultiplePathsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todo/list\", DELETE),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingProvidingRegexForPathVariableTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint having regex on path parameter using converts to a path without the regex`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = DELETE,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        )\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingOnFunctionWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingOnFunctionWithMultiplePathsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todo/list\", PATCH),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingProvidingRegexForPathVariableTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint having regex on path parameter using converts to a path without the regex`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PATCH,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        )\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingOnFunctionWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingOnFunctionWithMultiplePathsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todo/list\", POST),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingProvidingRegexForPathVariableTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint having regex on path parameter using converts to a path without the regex`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = POST,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        )\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingOnFunctionWithMultiplePathsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingOnFunctionWithMultiplePathsTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todo/list\", PUT),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingProvidingRegexForPathVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingProvidingRegexForPathVariableTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `endpoint having regex on path parameter using converts to a path without the regex`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PUT,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                pathParameters = setOf(\n                                        PathParameter(\"id\")\n                                )\n                        )\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n    }\n\n    @Nested\n    inner class ConjunctionTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingNestedPathController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingNestedPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `nested paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todo/list\", GET),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingNestedPathController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingNestedPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todo/list\", GET),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingNestedPathController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingNestedPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todo/list\", DELETE),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingNestedPathController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingNestedPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todo/list\", PATCH),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingNestedPathController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingNestedPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todo/list\", POST),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingNestedPathController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingNestedPathTest {\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple paths extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todo/list\", PUT),\n                        Endpoint(\"/todo/list\", OPTIONS),\n                        Endpoint(\"/todo/list\", HEAD)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/pathparameters/PathParameterTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.pathparameters\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.GetMapping\nimport org.springframework.web.bind.annotation.PathVariable\nimport org.springframework.web.bind.annotation.RequestMapping\nimport org.springframework.web.bind.annotation.RequestMethod.OPTIONS\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PathParameterNamedByVariableController {\n\n    @GetMapping(\"/{id}\")\n    fun getSpecificTodoItem(@PathVariable id: Int) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PathParameterNamedByValueAttributeController {\n\n    @GetMapping(\"/{id}\")\n    fun getSpecificTodoItem(@PathVariable(value = \"id\") variable: Int) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PathParameterNamedByNameAttributeController {\n\n    @GetMapping(\"/{id}\")\n    fun getSpecificTodoItem(@PathVariable(name = \"id\") variable: Int) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PathParameterHavingBothValueAndNameAttributeController {\n\n    @GetMapping(\"/{id}\")\n    fun getSpecificTodoItem(@PathVariable(value = \"valueAttribute\", name = \"nameAttribute\") variable: Int) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PathParameterSupportedForOptionsIfExplicitlyDefinedController {\n\n    @RequestMapping(\"/todos/{id}\", method = [OPTIONS])\n    fun getSpecificTodoItem(@PathVariable id: Int) { }\n}\n\n@Controller\n@RequestMapping(\"/todos\")\n@Suppress(\"UNUSED_PARAMETER\")\nopen class PathParameterOnDefaultErrorEndpointController {\n\n    @GetMapping(\"/{id}\")\n    fun getSpecificTodoItem(@PathVariable(value = \"id\") variable: Int) { }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/pathparameters/SpringConverterPathParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.pathparameters\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport org.springframework.http.MediaType.TEXT_HTML_VALUE\nimport kotlin.test.assertFailsWith\n\nclass SpringConverterPathParameterTest {\n\n    @Nested\n    @WebMvcTest(PathParameterNamedByVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class PathParameterNamedByVariableTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `path parameter name defined by variable name`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                PathParameter(\"id\")\n                            )\n                    ),\n                    Endpoint(\"/todos/{id}\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                PathParameter(\"id\")\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(PathParameterNamedByValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class PathParameterNamedByValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `path parameter name defined by 'value' attribute`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    ),\n                    Endpoint(\"/todos/{id}\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(PathParameterNamedByNameAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class PathParameterNamedByNameAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `path parameter name defined by 'name' attribute`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    ),\n                    Endpoint(\"/todos/{id}\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(PathParameterHavingBothValueAndNameAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class PathParameterHavingBothValueAndNameAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `path parameter name defined by both 'value' and 'name' attribute`() {\n            assertFailsWith<IllegalStateException> {\n                SpringConverter(context).conversionResult\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(PathParameterSupportedForOptionsIfExplicitlyDefinedController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class PathParameterSupportedForOptionsIfExplicitlyDefinedTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `path parameter are supported for OPTIONS if defined explicitly`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = OPTIONS,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    ),\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(PathParameterOnDefaultErrorEndpointController::class)\n    inner class PathParameterOnDefaultErrorEndpointTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `path parameters are not added to default error endpoint`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = GET,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    ),\n                    Endpoint(\"/todos/{id}\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos/{id}\",\n                            httpMethod = HEAD,\n                            pathParameters = setOf(\n                                    PathParameter(\"id\")\n                            )\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/redirect/RedirectTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.redirect\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.web.bind.annotation.GetMapping\nimport org.springframework.web.bind.annotation.ResponseBody\nimport org.springframework.web.bind.annotation.RestController\nimport org.springframework.web.servlet.view.RedirectView\nimport javax.servlet.http.HttpServletResponse\n\n@SpringBootApplication\nopen class DummyApp\n\n@RestController\nopen class RedirectTestController {\n\n    @GetMapping(\"/todos\")\n    fun todos(): RedirectView = RedirectView()\n}\n\n@RestController\nopen class RedirectUsingHttpServletResponseTestController {\n\n    @GetMapping(\"/todos\")\n    @ResponseBody\n    fun getTest(response: HttpServletResponse) {\n        response.sendRedirect(\"http://localhost:8080/other\")\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/redirect/SpringControllerRedirectTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.redirect\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\n\nclass SpringControllerRedirectTest {\n\n    @Nested\n    @WebMvcTest(RedirectTestController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class ReturnsRedirectViewTest {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `produces not set if the return type is RedirectView`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\"/todos\", GET, produces = emptySet()),\n                Endpoint(\"/todos\", HEAD, produces = emptySet()),\n                Endpoint(\"/todos\", OPTIONS, produces = emptySet())\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(RedirectUsingHttpServletResponseTestController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class RedirectUsingHttpServletResponseTest {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `produces is empty if there is no return type, because redirect is done using HttpServletResponse`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\"/todos\", GET, produces = emptySet()),\n                Endpoint(\"/todos\", HEAD, produces = emptySet()),\n                Endpoint(\"/todos\", OPTIONS, produces = emptySet())\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/responsebody/ProducesResponseBodyAnnotationTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.responsebody\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.http.MediaType.*\nimport org.springframework.http.ResponseEntity\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.*\n\n@SpringBootApplication\nopen class DummyApp\n\ndata class Todo(val description: String = \"\")\n\n@Controller\n@ResponseBody\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\nopen class RequestMappingOneMediaTypeIsInheritedByAllFunctionsController {\n\n    @RequestMapping\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController())\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\nopen class RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController {\n\n    @RequestMapping\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController())\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnClassDefaultValueController {\n\n    @RequestMapping\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOnClassDefaultValueController())\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(\"/todos\")\nopen class RequestMappingWithoutProducesOnClassInfoAndStringAsResponseBodyValueController {\n\n    @RequestMapping\n    fun getAllTodos() = \"\"\n}\n\n@Controller\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnClassWithoutResponseBodyAnnotationController {\n\n    @RequestMapping\n    fun getAllTodos() { }\n}\n\n@RestController\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnClassNoProducesInfoAndNoReturnTypeController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\nopen class RequestMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class RequestMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class RequestMappingOnFunctionDefaultValueController {\n\n    @RequestMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOnFunctionDefaultValueController())\n}\n\n@Controller\n@ResponseBody\nopen class RequestMappingWithoutProducesOnFunctionInfoAndStringAsResponseBodyValueController {\n\n    @RequestMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@Controller\nopen class RequestMappingOnFunctionWithoutResponseBodyAnnotationController {\n\n    @RequestMapping(\"/todos\")\n    fun getAllTodos() { }\n}\n\n@RestController\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnFunctionNoProducesInfoAndNoReturnTypeController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\nopen class GetMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @GetMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class GetMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @GetMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class GetMappingDefaultValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingDefaultValueController())\n}\n\n@Controller\n@ResponseBody\nopen class GetMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@Controller\nopen class GetMappingWithoutResponseBodyAnnotationController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos() { }\n}\n\n@RestController\nopen class GetMappingNoProducesInfoAndNoReturnTypeController {\n\n    @GetMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\nopen class DeleteMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @DeleteMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(DeleteMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @DeleteMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class DeleteMappingDefaultValueController {\n\n    @DeleteMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(DeleteMappingDefaultValueController())\n}\n\n@Controller\n@ResponseBody\nopen class DeleteMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @DeleteMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@Controller\nopen class DeleteMappingWithoutResponseBodyAnnotationController {\n\n    @DeleteMapping(\"/todos\")\n    fun getAllTodos() { }\n}\n\n@RestController\nopen class DeleteMappingNoProducesInfoAndNoReturnTypeController {\n\n    @DeleteMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\nopen class PatchMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PatchMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PatchMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class PatchMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PatchMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PatchMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class PatchMappingDefaultValueController {\n\n    @PatchMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(PatchMappingDefaultValueController())\n}\n\n@Controller\n@ResponseBody\nopen class PatchMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @PatchMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@Controller\nopen class PatchMappingWithoutResponseBodyAnnotationController {\n\n    @PatchMapping(\"/todos\")\n    fun getAllTodos() { }\n}\n\n@RestController\nopen class PatchMappingNoProducesInfoAndNoReturnTypeController {\n\n    @PatchMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\nopen class PostMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PostMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PostMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class PostMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PostMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PostMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class PostMappingDefaultValueController {\n\n    @PostMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(PostMappingDefaultValueController())\n}\n\n@Controller\nopen class PostMappingWithoutResponseBodyAnnotationController {\n\n    @PostMapping(\"/todos\")\n    fun getAllTodos() { }\n}\n\n@Controller\n@ResponseBody\nopen class PostMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @PostMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\nopen class PostMappingNoProducesInfoAndNoReturnTypeController {\n\n    @PostMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\nopen class PutMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PutMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PutMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class PutMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PutMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PutMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@Controller\n@ResponseBody\nopen class PutMappingDefaultValueController {\n\n    @PutMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(PutMappingDefaultValueController())\n}\n\n@Controller\n@ResponseBody\nopen class PutMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @PutMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@Controller\nopen class PutMappingWithoutResponseBodyAnnotationController {\n\n    @PutMapping(\"/todos\")\n    fun getAllTodos() { }\n}\n\n@RestController\nopen class PutMappingNoProducesInfoAndNoReturnTypeController {\n\n    @PutMapping(\"/todos\")\n    fun todos() { }\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\nopen class RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController {\n\n    @RequestMapping(produces = [TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController())\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController {\n\n    @RequestMapping(produces = [TEXT_PLAIN_VALUE, \"application/pdf\"])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController())\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class GetMappingOneMediaTypeIsOverwrittenController {\n\n    @GetMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class DeleteMappingOneMediaTypeIsOverwrittenController {\n\n    @DeleteMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class PatchMappingOneMediaTypeIsOverwrittenController {\n\n    @PatchMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class PostMappingOneMediaTypeIsOverwrittenController {\n\n    @PostMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class PutMappingOneMediaTypeIsOverwrittenController {\n\n    @PutMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class GetMappingMultipleMediaTypesAreOverwrittenController {\n\n    @GetMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class DeleteMappingMultipleMediaTypesAreOverwrittenController {\n\n    @DeleteMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class PatchMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PatchMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class PostMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PostMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class PutMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PutMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@Controller\n@ResponseBody\nopen class ErrorEndpointController {\n\n    @GetMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(ErrorEndpointController())\n}"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/responsebody/SpringConverterProducesResponseBodyAnnotationTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.responsebody\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.*\n\nclass SpringConverterProducesResponseBodyAnnotationTest {\n\n    @Nested\n    inner class RequestMappingAnnotationTests {\n\n        @Nested\n        inner class ClassLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class OneMediaTypeIsInheritedByAllFunctionsTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `media type declared at class level using RequestMapping annotation is inherited by all functions`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleMediaTypesAreInheritedByAllFunctionsTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple media types declared at class level using RequestMapping annotation are inherited by all functions`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassUsingDefaultValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared at class level will fallback to default media type`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingWithoutProducesOnClassInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoResponseBodyAnnotationTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no ResponseBody annotation results in an empty produces list`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoProducesInfoAndNoReturnTypeTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and no return type results in produces being empty`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n\n        @Nested\n        inner class FunctionLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `media type declared at function level using RequestMapping annotation is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple media types declared at function level using RequestMapping annotation are extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionUsingDefaultValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared at function level will fallback to default media type`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingWithoutProducesOnFunctionInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoResponseBodyAnnotationTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no ResponseBody annotation results in an empty produces list`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoProducesInfoAndNoReturnTypeTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and no return type results in produces being empty`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class GetMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(GetMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using GetMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using GetMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoResponseBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no ResponseBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class DeleteMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(DeleteMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using DeleteMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using DeleteMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoResponseBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no ResponseBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PatchMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PatchMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PatchMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PatchMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoResponseBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no ResponseBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PostMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PostMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PostMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PostMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoResponseBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no ResponseBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PutMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PutMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PutMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PutMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingWithoutResponseBodyAnnotationController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoResponseBodyAnnotationTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no ResponseBody annotation results in an empty produces list`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class OverwriteTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by a declaration at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by a declaration at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by GetMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by DeleteMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PatchMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PostMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PutMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by GetMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by DeleteMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PatchMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PostMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PutMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(ErrorEndpointController::class)\n    inner class MediaTypeIsNotAddedToDefaultErrorEndpoint {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `error endpoint does not provide the same media type`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_XML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_XML_VALUE)\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/restcontroller/ProducesRestControllerAnnotationTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.restcontroller\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.http.MediaType.*\nimport org.springframework.http.ResponseEntity\nimport org.springframework.web.bind.annotation.*\n\n@SpringBootApplication\nopen class DummyApp\n\ndata class Todo(val description: String = \"\")\n\n@RestController\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\nopen class RequestMappingOneMediaTypeIsInheritedByAllFunctionsController {\n\n    @RequestMapping\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController())\n}\n\n@RestController\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\nopen class RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController {\n\n    @RequestMapping\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController())\n}\n\n@RestController\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnClassDefaultValueController {\n\n    @RequestMapping\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOnClassDefaultValueController())\n}\n\n@RestController\n@RequestMapping(\"/todos\")\nopen class RequestMappingWithoutProducesOnClassInfoAndStringAsResponseBodyValueController {\n\n    @RequestMapping\n    fun getAllTodos() = \"\"\n}\n\n@RestController\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnClassNoProducesInfoAndNoReturnTypeController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@RestController\nopen class RequestMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@RestController\nopen class RequestMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@RestController\nopen class RequestMappingOnFunctionDefaultValueController {\n\n    @RequestMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOnFunctionDefaultValueController())\n}\n\n@RestController\nopen class RequestMappingWithoutProducesOnFunctionInfoAndStringAsResponseBodyValueController {\n\n    @RequestMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\n@RequestMapping(\"/todos\")\nopen class RequestMappingOnFunctionNoProducesInfoAndNoReturnTypeController {\n\n    @RequestMapping\n    fun todos() { }\n}\n\n@RestController\nopen class GetMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @GetMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@RestController\nopen class GetMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @GetMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@RestController\nopen class GetMappingDefaultValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingDefaultValueController())\n}\n\n@RestController\nopen class GetMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\nopen class GetMappingNoProducesInfoAndNoReturnTypeController {\n\n    @GetMapping(\"/todos\")\n    fun todos() { }\n}\n\n@RestController\nopen class DeleteMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @DeleteMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(DeleteMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@RestController\nopen class DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @DeleteMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@RestController\nopen class DeleteMappingDefaultValueController {\n\n    @DeleteMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(DeleteMappingDefaultValueController())\n}\n\n@RestController\nopen class DeleteMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @DeleteMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\nopen class DeleteMappingNoProducesInfoAndNoReturnTypeController {\n\n    @DeleteMapping(\"/todos\")\n    fun todos() { }\n}\n\n@RestController\nopen class PatchMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PatchMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PatchMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@RestController\nopen class PatchMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PatchMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PatchMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@RestController\nopen class PatchMappingDefaultValueController {\n\n    @PatchMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(PatchMappingDefaultValueController())\n}\n\n@RestController\nopen class PatchMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @PatchMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\nopen class PatchMappingNoProducesInfoAndNoReturnTypeController {\n\n    @PatchMapping(\"/todos\")\n    fun todos() { }\n}\n\n@RestController\nopen class PostMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PostMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PostMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@RestController\nopen class PostMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PostMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PostMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@RestController\nopen class PostMappingDefaultValueController {\n\n    @PostMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(PostMappingDefaultValueController())\n}\n\n@RestController\nopen class PostMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @PostMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\nopen class PostMappingNoProducesInfoAndNoReturnTypeController {\n\n    @PostMapping(\"/todos\")\n    fun todos() { }\n}\n\n@RestController\nopen class PutMappingOneMediaTypeIsExtractedCorrectlyController {\n\n    @PutMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PutMappingOneMediaTypeIsExtractedCorrectlyController())\n}\n\n@RestController\nopen class PutMappingMultipleMediaTypesAreExtractedCorrectlyController {\n\n    @PutMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(PutMappingMultipleMediaTypesAreExtractedCorrectlyController())\n}\n\n@RestController\nopen class PutMappingDefaultValueController {\n\n    @PutMapping(\"/todos\")\n    fun getAllTodos() = ResponseEntity.status(200).body(PutMappingDefaultValueController())\n}\n\n@RestController\nopen class PutMappingWithoutProducesInfoAndStringAsResponseBodyValueController {\n\n    @PutMapping(\"/todos\")\n    fun getAllTodos() = \"\"\n}\n\n@RestController\nopen class PutMappingNoProducesInfoAndNoReturnTypeController {\n\n    @PutMapping(\"/todos\")\n    fun todos() { }\n}\n\n@RestController\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\nopen class RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController {\n\n    @RequestMapping(produces = [TEXT_PLAIN_VALUE])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController())\n}\n\n@RestController\n@RequestMapping(\"/todos\", produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController {\n\n    @RequestMapping(produces = [TEXT_PLAIN_VALUE, \"application/pdf\"])\n    fun getAllTodos() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController())\n\n    @RequestMapping(\"/{id}\")\n    fun getSpecificTodo() = ResponseEntity.status(200).body(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController())\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class GetMappingOneMediaTypeIsOverwrittenController {\n\n    @GetMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class DeleteMappingOneMediaTypeIsOverwrittenController {\n\n    @DeleteMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class PatchMappingOneMediaTypeIsOverwrittenController {\n\n    @PatchMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class PostMappingOneMediaTypeIsOverwrittenController {\n\n    @PostMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE])\nopen class PutMappingOneMediaTypeIsOverwrittenController {\n\n    @PutMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class GetMappingMultipleMediaTypesAreOverwrittenController {\n\n    @GetMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class DeleteMappingMultipleMediaTypesAreOverwrittenController {\n\n    @DeleteMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class PatchMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PatchMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class PostMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PostMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\n@RequestMapping(produces = [APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE])\nopen class PutMappingMultipleMediaTypesAreOverwrittenController {\n\n    @PutMapping(\"/todos\", produces = [TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE])\n    fun todos() = Todo()\n}\n\n@RestController\nopen class ErrorEndpointController {\n\n    @GetMapping(\"/todos\", produces = [APPLICATION_XML_VALUE])\n    fun todos() = ResponseEntity.status(200).body(ErrorEndpointController())\n}"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/restcontroller/SpringConverterProducesRestControllerAnnotationTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.restcontroller\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType.*\n\nclass SpringConverterProducesRestControllerAnnotationTest {\n\n    @Nested\n    inner class RequestMappingAnnotationTests {\n\n        @Nested\n        inner class ClassLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOneMediaTypeIsInheritedByAllFunctionsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class OneMediaTypeIsInheritedByAllFunctionsTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `media type declared at class level using RequestMapping annotation is inherited by all functions`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipleMediaTypesAreInheritedByAllFunctionsController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleMediaTypesAreInheritedByAllFunctionsTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple media types declared at class level using RequestMapping annotation are inherited by all functions`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos/{id}\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos/{id}\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnClassUsingDefaultValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared at class level will fallback to default media type`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingWithoutProducesOnClassInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnClassNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoProducesInfoAndNoReturnTypeTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and no return type results in produces being empty`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n\n        @Nested\n        inner class FunctionLevelTests {\n\n            @Nested\n            @WebMvcTest(RequestMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `media type declared at function level using RequestMapping annotation is extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `multiple media types declared at function level using RequestMapping annotation are extracted correctly`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class DefinedOnFunctionUsingDefaultValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared at function level will fallback to default media type`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(APPLICATION_JSON_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingWithoutProducesOnFunctionInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = GET,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = POST,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = HEAD,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PUT,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = PATCH,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\n                                    path = \"/todos\",\n                                    httpMethod = DELETE,\n                                    produces = setOf(TEXT_PLAIN_VALUE)\n                            ),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n\n            @Nested\n            @WebMvcTest(RequestMappingOnFunctionNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n            inner class NoProducesInfoAndNoReturnTypeTest {\n\n                @Autowired\n                lateinit var context: ConfigurableApplicationContext\n\n                @Test\n                fun `no media type declared and no return type results in produces being empty`() {\n                    //given\n                    val specification: Set<Endpoint> = setOf(\n                            Endpoint(\"/todos\", GET),\n                            Endpoint(\"/todos\", PUT),\n                            Endpoint(\"/todos\", POST),\n                            Endpoint(\"/todos\", DELETE),\n                            Endpoint(\"/todos\", PATCH),\n                            Endpoint(\"/todos\", HEAD),\n                            Endpoint(\"/todos\", OPTIONS)\n                    )\n\n                    //when\n                    val implementation = SpringConverter(context)\n\n                    //then\n                    assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n                }\n            }\n        }\n    }\n\n    @Nested\n    inner class GetMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(GetMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using GetMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using GetMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", GET),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class DeleteMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(DeleteMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using DeleteMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using DeleteMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", DELETE),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PatchMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PatchMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PatchMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PatchMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PATCH),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PostMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PostMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PostMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PostMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", POST),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class PutMappingAnnotationTests {\n\n        @Nested\n        @WebMvcTest(PutMappingOneMediaTypeIsExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class OneMediaTypeIsExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at function level using PutMapping annotation is extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingMultipleMediaTypesAreExtractedCorrectlyController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class MultipleMediaTypesAreExtractedCorrectlyTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `multiple media types declared at function level using PutMapping annotation are extracted correctly`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DefinedOnFunctionUsingDefaultValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared at function level will fallback to default media type`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_JSON_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingWithoutProducesInfoAndStringAsResponseBodyValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoConsumesInfoAndStringAsReturnValueTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and kotlin String as request body will lead to plain text`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingNoProducesInfoAndNoReturnTypeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class NoProducesInfoAndNoReturnTypeTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `no media type declared and no return type results in produces being empty`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\"/todos\", PUT),\n                        Endpoint(\"/todos\", HEAD),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    inner class OverwriteTests {\n\n        @Nested\n        @WebMvcTest(RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingOneMediaTypeIsOverwrittenByDeclarationOnFunctionTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by a declaration at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class RequestMappingMultipleMediaTypesAreOverwrittenByDeclarationOnFunctionTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by a declaration at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = GET,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = POST,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = HEAD,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PUT,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = PATCH,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos/{id}\",\n                                httpMethod = DELETE,\n                                produces = setOf(APPLICATION_XML_VALUE, APPLICATION_XHTML_XML_VALUE)\n                        ),\n                        Endpoint(\"/todos/{id}\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by GetMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by DeleteMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PatchMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PostMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingOneMediaTypeIsOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingOneMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PutMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(GetMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class GetMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by GetMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = GET,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(DeleteMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class DeleteMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by DeleteMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = DELETE,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PatchMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PatchMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PatchMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PATCH,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PostMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PostMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PostMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = POST,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n\n        @Nested\n        @WebMvcTest(PutMappingMultipleMediaTypesAreOverwrittenController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n        inner class PutMappingMultipleMediaTypeIsOverwrittenTest {\n\n            @Autowired\n            lateinit var context: ConfigurableApplicationContext\n\n            @Test\n            fun `media type declared at class level using RequestMapping is overwritten by PutMapping at function level`() {\n                //given\n                val specification: Set<Endpoint> = setOf(\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = PUT,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\n                                path = \"/todos\",\n                                httpMethod = HEAD,\n                                produces = setOf(TEXT_PLAIN_VALUE, APPLICATION_PDF_VALUE)\n                        ),\n                        Endpoint(\"/todos\", OPTIONS)\n                )\n\n                //when\n                val implementation = SpringConverter(context)\n\n                //then\n                assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(ErrorEndpointController::class)\n    inner class MediaTypeIsNotAddedToDefaultErrorEndpoint {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `error endpoint does not provide the same media type`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_XML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_XML_VALUE)\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/servletresponse/ProducesServletResponseTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.servletresponse\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.*\nimport javax.servlet.http.HttpServletResponse\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\nopen class ProducesServletResponseTestController {\n    @GetMapping(\"/todos\", produces = [\"text/plain\"])\n    @ResponseBody\n    fun getTest(response: HttpServletResponse) {\n        response.outputStream.println(\"Hello, world!\")\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/produces/servletresponse/SpringConverterProducesServletResponseTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.produces.servletresponse\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\n\nclass SpringConverterProducesServletResponseTest {\n\n    @Nested\n    @WebMvcTest(ProducesServletResponseTestController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class NoProducesInfoAndNoReturnTypeTest {\n\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `media type and response servlet argument declared and no return type results in proper media type`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\"/todos\", GET, produces = setOf(\"text/plain\")),\n                    Endpoint(\"/todos\", HEAD, produces = setOf(\"text/plain\")),\n                    Endpoint(\"/todos\", OPTIONS, produces = emptySet())\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/queryparameters/QueryParameterTestController.kt",
    "content": "package de.codecentric.hikaku.converters.spring.queryparameters\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annotation.GetMapping\nimport org.springframework.web.bind.annotation.RequestParam\n\n@SpringBootApplication\nopen class DummyApp\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterNamedByVariableController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam tag: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterNamedByValueAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam(value = \"tag\") variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterNamedByNameAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam(name = \"tag\") variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterHavingBothNameAndValueAttributeController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam(value=\"valueAttribute\", name = \"nameAttribute\") variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterOptionalController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam(name = \"tag\", required = false) variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterOptionalBecauseOfDefaultValueController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam(name = \"tag\", defaultValue = \"mytag\") variable: String) { }\n}\n\n@Controller\n@Suppress(\"UNUSED_PARAMETER\")\nopen class QueryParameterOnDefaultErrorEndpointController {\n\n    @GetMapping(\"/todos\")\n    fun getAllTodos(@RequestParam(value = \"tag\", required = false) variable: String) { }\n}\n"
  },
  {
    "path": "spring/src/test/kotlin/de/codecentric/hikaku/converters/spring/queryparameters/SpringConverterQueryParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.spring.queryparameters\n\nimport de.codecentric.hikaku.converters.spring.SpringConverter\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport org.springframework.beans.factory.annotation.Autowired\nimport org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest\nimport org.springframework.context.ConfigurableApplicationContext\nimport org.springframework.http.MediaType\nimport org.springframework.http.MediaType.APPLICATION_JSON_VALUE\nimport kotlin.test.assertFailsWith\n\nclass SpringConverterQueryParameterTest {\n\n    @Nested\n    @WebMvcTest(QueryParameterNamedByVariableController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class QueryParameterNamedByVariableTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `query parameter name defined by variable name`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        queryParameters = setOf(\n                                QueryParameter(\"tag\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(QueryParameterNamedByValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class QueryParameterNamedByValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `query parameter name defined by attribute 'value'`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(QueryParameterNamedByNameAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class QueryParameterNamedByNameAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `query parameter name defined by attribute 'name'`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", true)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", true)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(QueryParameterHavingBothNameAndValueAttributeController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class QueryParameterHavingBothNameAndValueAttributeTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `both 'value' and 'name' attribute defined for query parameter`() {\n            assertFailsWith<IllegalStateException> {\n                SpringConverter(context).conversionResult\n            }\n        }\n    }\n\n    @Nested\n    @WebMvcTest(QueryParameterOptionalController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class QueryParameterOptionalTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `query parameter set to optional`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            queryParameters = setOf(\n                                QueryParameter(\"tag\", false)\n                            )\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            queryParameters = setOf(\n                                QueryParameter(\"tag\", false)\n                            )\n                    )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(QueryParameterOptionalBecauseOfDefaultValueController::class, excludeAutoConfiguration = [ErrorMvcAutoConfiguration::class])\n    inner class QueryParameterOptionalBecauseOfDefaultValueTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `query parameter optional, because of a default value`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", false)\n                        )\n                ),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = HEAD,\n                        queryParameters = setOf(\n                            QueryParameter(\"tag\", false)\n                        )\n                )\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n\n    @Nested\n    @WebMvcTest(QueryParameterOnDefaultErrorEndpointController::class)\n    inner class QueryParameterOnDefaultErrorEndpointTest {\n        @Autowired\n        lateinit var context: ConfigurableApplicationContext\n\n        @Test\n        fun `query parameters are not added to default error endpoint`() {\n            //given\n            val specification: Set<Endpoint> = setOf(\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = GET,\n                            queryParameters = setOf(\n                                    QueryParameter(\"tag\")\n                            )\n                    ),\n                    Endpoint(\"/todos\", OPTIONS),\n                    Endpoint(\n                            path = \"/todos\",\n                            httpMethod = HEAD,\n                            queryParameters = setOf(\n                                    QueryParameter(\"tag\")\n                            )\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(APPLICATION_JSON_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = GET,\n                            produces = setOf(MediaType.TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = POST,\n                            produces = setOf(MediaType.TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = HEAD,\n                            produces = setOf(MediaType.TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PUT,\n                            produces = setOf(MediaType.TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = PATCH,\n                            produces = setOf(MediaType.TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\n                            path = \"/error\",\n                            httpMethod = DELETE,\n                            produces = setOf(MediaType.TEXT_HTML_VALUE)\n                    ),\n                    Endpoint(\"/error\", OPTIONS)\n            )\n\n            //when\n            val implementation = SpringConverter(context)\n\n            //then\n            assertThat(implementation.conversionResult).containsExactlyInAnyOrderElementsOf(specification)\n        }\n    }\n}\n"
  },
  {
    "path": "spring/src/test/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "wadl/README.md",
    "content": "# hikaku - WADL\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md). To check the feature support for this converter.\n\n## Usage\n\nThe WadlConverter can be used either with a `File` or a `Path` object."
  },
  {
    "path": "wadl/build.gradle",
    "content": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-wadl'\n\ndependencies {\n  api project(':core')\n}\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n      pom.project {\n        name = 'hikaku-wadl'\n        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for WADL files.'\n      }\n    }\n  }\n}"
  },
  {
    "path": "wadl/src/main/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverter.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.converters.AbstractEndpointConverter\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport de.codecentric.hikaku.converters.wadl.extensions.getAttribute\nimport de.codecentric.hikaku.endpoints.*\nimport de.codecentric.hikaku.extensions.checkFileValidity\nimport org.w3c.dom.Node\nimport org.w3c.dom.NodeList\nimport org.xml.sax.InputSource\nimport java.io.File\nimport java.io.StringReader\nimport java.nio.charset.Charset\nimport java.nio.charset.StandardCharsets.UTF_8\nimport java.nio.file.Files\nimport java.nio.file.Path\nimport javax.xml.parsers.DocumentBuilderFactory\nimport javax.xml.xpath.XPathConstants.NODESET\nimport javax.xml.xpath.XPathFactory\n\n/**\n * Extracts and converts [Endpoint]s from a *.wadl* file.\n */\nclass WadlConverter private constructor(private val wadl: String) : AbstractEndpointConverter() {\n\n    @JvmOverloads\n    constructor(wadlFile: File, charset: Charset = UTF_8): this(wadlFile.toPath(), charset)\n    @JvmOverloads\n    constructor(wadlFile: Path, charset: Charset = UTF_8): this(readFileContent(wadlFile, charset))\n\n    override val supportedFeatures = SupportedFeatures(\n            Feature.QueryParameters,\n            Feature.HeaderParameters,\n            Feature.PathParameters,\n            Feature.MatrixParameters,\n            Feature.Produces,\n            Feature.Consumes\n    )\n\n    private val xPath = XPathFactory\n            .newInstance()\n            .newXPath()\n\n    override fun convert(): Set<Endpoint> {\n        try {\n            return parseWadl()\n        } catch (throwable: Throwable) {\n            throw EndpointConverterException(throwable)\n        }\n    }\n\n    private fun parseWadl(): Set<Endpoint> {\n        val doc = DocumentBuilderFactory\n                .newInstance()\n                .newDocumentBuilder()\n                .parse(InputSource(StringReader(wadl)))\n\n        val resources = xPath.evaluate(\"//resource\", doc, NODESET) as NodeList\n\n        val endpoints = mutableSetOf<Endpoint>()\n\n        for (index in 0 until resources.length) {\n            endpoints.addAll(createEndpoints(resources.item(index)))\n        }\n\n        return endpoints\n    }\n\n    private fun createEndpoints(resourceElement: Node): Set<Endpoint> {\n        val path = resourceElement.getAttribute(\"path\")\n\n        val methods = xPath.evaluate(\"//resource[@path=\\\"$path\\\"]//method\", resourceElement.childNodes, NODESET) as NodeList\n        val endpoints: MutableSet<Endpoint> = mutableSetOf()\n\n        for (i in 0 until methods.length) {\n            val method = methods.item(i)\n            val httpMethod = HttpMethod.valueOf(method.getAttribute(\"name\"))\n\n            endpoints.add(\n                    Endpoint(\n                            path = path,\n                            httpMethod = httpMethod,\n                            queryParameters = extractQueryParameters(method),\n                            headerParameters = extractHeaderParameters(method),\n                            pathParameters = extractPathParameters(method),\n                            matrixParameters = extractMatrixParameters(method),\n                            produces = extractResponseMediaTypes(method),\n                            consumes = extractConsumesMediaTypes(method)\n                    )\n            )\n        }\n\n        return endpoints\n    }\n\n    private fun extractResponseMediaTypes(method: Node) = extractMediaTypes(method, \"response\")\n\n    private fun extractConsumesMediaTypes(method: Node) = extractMediaTypes(method, \"request\")\n\n    private fun extractMediaTypes(method: Node, xmlBaseElement: String): Set<String> {\n        val representations = xPath.evaluate(\"//$xmlBaseElement/representation\", method.childNodes, NODESET) as NodeList\n        val mediaTypes: MutableSet<String> = mutableSetOf()\n\n        for (i in 0 until representations.length) {\n            val parameter = representations.item(i)\n            mediaTypes += parameter.getAttribute(\"mediaType\")\n        }\n\n        return mediaTypes\n    }\n\n    private fun extractPathParameters(method: Node): Set<PathParameter> {\n        return extractParameter(method, \"template\")\n                .entries\n                .map { PathParameter(it.key) }\n                .toSet()\n    }\n\n    private fun extractQueryParameters(method: Node): Set<QueryParameter> {\n        return extractParameter(method, \"query\")\n                .entries\n                .map { QueryParameter(it.key, it.value) }\n                .toSet()\n    }\n\n    private fun extractHeaderParameters(method: Node): Set<HeaderParameter> {\n        return extractParameter(method, \"header\")\n                .entries\n                .map { HeaderParameter(it.key, it.value) }\n                .toSet()\n    }\n\n    private fun extractMatrixParameters(method: Node): Set<MatrixParameter> {\n        return extractParameter(method, \"matrix\")\n                .entries\n                .map { MatrixParameter(it.key, it.value) }\n                .toSet()\n    }\n\n    private fun extractParameter(method: Node, style: String): Map<String, Boolean> {\n        val parameters = xPath.evaluate(\"//param[@style=\\\"$style\\\"]\", method.childNodes, NODESET) as NodeList\n        val parameterMap: MutableMap<String, Boolean> = mutableMapOf()\n\n        for (i in 0 until parameters.length) {\n            val parameter = parameters.item(i)\n            val parameterName = parameter.getAttribute(\"name\")\n            val isParameterRequired = \"true\" == parameter.getAttribute(\"required\")\n\n            parameterMap[parameterName] = isParameterRequired\n        }\n\n        return parameterMap\n    }\n}\n\nprivate fun readFileContent(wadlFile: Path, charset: Charset): String {\n    val fileContentBuilder = StringBuilder()\n\n    try {\n        wadlFile.checkFileValidity(\".wadl\")\n\n        Files.readAllLines(wadlFile, charset)\n                .map { line ->\n                    fileContentBuilder\n                            .append(line)\n                            .append(\"\\n\")\n                }\n    } catch (throwable: Throwable) {\n        throw EndpointConverterException(throwable)\n    }\n\n    val fileContent = fileContentBuilder.toString()\n\n    if (fileContent.isBlank()) {\n        throw EndpointConverterException(\"Given WADL is blank.\")\n    }\n\n    return fileContent\n}"
  },
  {
    "path": "wadl/src/main/kotlin/de/codecentric/hikaku/converters/wadl/extensions/NodeExtensions.kt",
    "content": "package de.codecentric.hikaku.converters.wadl.extensions\n\nimport org.w3c.dom.Node\n\ninternal fun Node.getAttribute(identifier: String): String {\n    return this.attributes.getNamedItem(identifier).textContent\n}"
  },
  {
    "path": "wadl/src/main/resources/.gitemptydir",
    "content": ""
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterConsumesTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass WadlConverterConsumesTest {\n\n    @Test\n    fun `check that media type information for the response are extracted correctly`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/consumes_three_media_types.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"application/xml\",\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val specification = WadlConverter(file).conversionResult\n\n        //then\n        assertThat(specification).isEqualTo(implementation)\n    }\n\n    @Test\n    fun `check that no media type information result in empty consumes list`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/consumes_no_media_types.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\"/todos\", GET)\n        )\n\n        //when\n        val specification = WadlConverter(file).conversionResult\n\n        //then\n        assertThat(specification).isEqualTo(implementation)\n    }\n\n    @Test\n    fun `check that media types are not extracted from response info`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"consumes/consumes_media_types_not_taken_from_produces.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"application/xml\",\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val specification = WadlConverter(file).conversionResult\n\n        //then\n        assertThat(specification).isEqualTo(implementation)\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterEndpointTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.*\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass WadlConverterEndpointTest {\n    \n    @Test\n    fun `extract two different paths`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"endpoints/endpoints_two_different_paths.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n            Endpoint(\"/todos\", GET),\n            Endpoint(\"/tags\", GET)\n        )\n\n        //when\n        val specification = WadlConverter(file)\n        \n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `extract two nested paths`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"endpoints/endpoints_two_nested_paths.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/todos/{id}\", GET)\n        )\n\n        //when\n        val specification = WadlConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n\n    @Test\n    fun `extract all http methods`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"endpoints/endpoints.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\"/todos\", GET),\n                Endpoint(\"/todos\", POST),\n                Endpoint(\"/todos\", PUT),\n                Endpoint(\"/todos\", PATCH),\n                Endpoint(\"/todos\", DELETE),\n                Endpoint(\"/todos\", HEAD),\n                Endpoint(\"/todos\", OPTIONS),\n                Endpoint(\"/todos\", TRACE),\n                Endpoint(\"/tags\", GET),\n                Endpoint(\"/tags\", POST),\n                Endpoint(\"/tags\", DELETE),\n                Endpoint(\"/tags\", HEAD),\n                Endpoint(\"/tags\", OPTIONS)\n        )\n\n        //when\n        val specification = WadlConverter(file)\n\n        //then\n        assertThat(specification.conversionResult).containsExactlyInAnyOrderElementsOf(implementation)\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterHeaderParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass WadlConverterHeaderParameterTest {\n\n    @Test\n    fun `check that header parameter are extracted correctly`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"header_parameters.wadl\").toURI())\n        val headerParameters = setOf(\n                HeaderParameter(\"x-b3-traceid\", false),\n                HeaderParameter(\"allow-cache\", true)\n        )\n\n        //when\n        val specification = WadlConverter(file)\n\n        //then\n        val resultingHeaderParameters = specification.conversionResult.toList()[0].headerParameters\n        assertThat(resultingHeaderParameters).containsExactlyInAnyOrderElementsOf(headerParameters)\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterInvalidInputTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport java.io.File\nimport java.nio.file.Paths\nimport kotlin.test.assertFailsWith\n\nclass WadlConverterInvalidInputTest {\n\n    @Nested\n    inner class PathObjectTests {\n\n        @Test\n        fun `empty file returns an empty list`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/empty_file.wadl\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                WadlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file consisting solely of whitespaces returns an empty list`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/whitespaces_only_file.wadl\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                WadlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file containing syntax error`() {\n            //given\n            val file = Paths.get(this::class.java.classLoader.getResource(\"invalid_input/syntax_error.wadl\").toURI())\n            val converter = WadlConverter(file)\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                converter.conversionResult\n            }\n        }\n    }\n\n    @Nested\n    inner class FileObjectTests {\n\n        @Test\n        fun `empty file returns an empty list`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/empty_file.wadl\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                WadlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file consisting solely of whitespaces returns an empty list`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/whitespaces_only_file.wadl\").toURI())\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                WadlConverter(file).conversionResult\n            }\n        }\n\n        @Test\n        fun `file containing syntax error`() {\n            //given\n            val file = File(this::class.java.classLoader.getResource(\"invalid_input/syntax_error.wadl\").toURI())\n            val converter = WadlConverter(file)\n\n            //when\n            assertFailsWith<EndpointConverterException> {\n                converter.conversionResult\n            }\n        }\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterMatrixParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.MatrixParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass WadlConverterMatrixParameterTest {\n\n    @Test\n    fun `check that matrix parameter are extracted correctly`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"matrix_parameters.wadl\").toURI())\n        val matrixParameters = setOf(\n                MatrixParameter(\"done\", false),\n                MatrixParameter(\"tag\", true)\n        )\n\n        //when\n        val specification = WadlConverter(file)\n\n        //then\n        val resultingMatrixParameters = specification.conversionResult.toList()[0].matrixParameters\n        assertThat(resultingMatrixParameters).containsExactlyInAnyOrderElementsOf(matrixParameters)\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterPathParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\n\nclass WadlConverterPathParameterTest {\n\n    @Test\n    fun `check that path parameter are extracted correctly`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"path_parameters.wadl\").toURI())\n        val pathParameter = PathParameter(\"id\")\n\n        //when\n        val specification = WadlConverter(file)\n\n        //then\n        val resultingPathParameters = specification.conversionResult.toList()[0].pathParameters\n        assertThat(resultingPathParameters).containsExactly(pathParameter)\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterProducesTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.endpoints.HttpMethod.GET\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass WadlConverterProducesTest {\n\n    @Test\n    fun `check that media type information for the response are extracted correctly`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_three_media_types.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        produces = setOf(\n                                \"application/json\",\n                                \"application/xml\",\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val specification = WadlConverter(file).conversionResult\n\n        //then\n        assertThat(specification).isEqualTo(implementation)\n    }\n\n    @Test\n    fun `check that no media type information result in empty consumes list`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_no_media_types.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\"/todos\", GET)\n        )\n\n        //when\n        val specification = WadlConverter(file).conversionResult\n\n        //then\n        assertThat(specification).isEqualTo(implementation)\n    }\n\n    @Test\n    fun `check that media types are not extracted from request info`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"produces/produces_media_types_not_taken_from_consumes.wadl\").toURI())\n        val implementation: Set<Endpoint> = setOf(\n                Endpoint(\n                        path = \"/todos\",\n                        httpMethod = GET,\n                        consumes = setOf(\n                                \"application/json\",\n                                \"application/xml\",\n                                \"text/plain\"\n                        )\n                )\n        )\n\n        //when\n        val specification = WadlConverter(file).conversionResult\n\n        //then\n        assertThat(specification).isEqualTo(implementation)\n    }\n}"
  },
  {
    "path": "wadl/src/test/kotlin/de/codecentric/hikaku/converters/wadl/WadlConverterQueryParameterTest.kt",
    "content": "package de.codecentric.hikaku.converters.wadl\n\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api.Test\nimport java.nio.file.Paths\n\nclass WadlConverterQueryParameterTest {\n\n    @Test\n    fun `check that query parameter are extracted correctly`() {\n        //given\n        val file = Paths.get(this::class.java.classLoader.getResource(\"query_parameters.wadl\").toURI())\n        val queryParameters = setOf(\n                QueryParameter(\"tag\", false),\n                QueryParameter(\"limit\", true)\n        )\n\n        //when\n        val specification = WadlConverter(file)\n\n        //then\n        val resultingQueryParameters = specification.conversionResult.toList()[0].queryParameters\n        assertThat(resultingQueryParameters).containsExactlyInAnyOrderElementsOf(queryParameters)\n    }\n}"
  },
  {
    "path": "wadl/src/test/resources/consumes/consumes_media_types_not_taken_from_produces.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\">\n          <representation mediaType=\"application/json\"/>\n          <representation mediaType=\"application/xml\"/>\n          <representation mediaType=\"text/plain\"/>\n        </response>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/consumes/consumes_no_media_types.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\" />\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/consumes/consumes_three_media_types.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <request>\n          <representation mediaType=\"application/json\"/>\n          <representation mediaType=\"application/xml\"/>\n          <representation mediaType=\"text/plain\"/>\n        </request>\n        <response status=\"200\" />\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/endpoints/endpoints.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"POST\" id=\"createTodo\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"PUT\" id=\"createOrUpdateTodo\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"PATCH\" id=\"partiallyUpdateTodo\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"DELETE\" id=\"deleteTodo\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"TRACE\" id=\"traceTodos\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"HEAD\" id=\"headTodos\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"OPTIONS\" id=\"optionsTodos\">\n        <response status=\"200\"/>\n      </method>\n    </resource>\n    <resource path=\"/tags\">\n      <method name=\"GET\" id=\"getAllTags\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"POST\" id=\"createTag\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"DELETE\" id=\"deleteTag\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"HEAD\" id=\"headTags\">\n        <response status=\"200\"/>\n      </method>\n      <method name=\"OPTIONS\" id=\"optionsTags\">\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/endpoints/endpoints_two_different_paths.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\"/>\n      </method>\n    </resource>\n    <resource path=\"/tags\">\n      <method name=\"GET\" id=\"getAllTags\">\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/endpoints/endpoints_two_nested_paths.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\"/>\n      </method>\n    </resource>\n    <resource path=\"/todos/{id}\">\n      <method name=\"GET\" id=\"getAllTags\">\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/header_parameters.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <request>\n          <param name=\"x-b3-traceid\" type=\"xsd:string\" style=\"header\" required=\"false\"/>\n          <param name=\"allow-cache\" type=\"xsd:boolean\" style=\"header\" required=\"true\"/>\n        </request>\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/invalid_input/empty_file.wadl",
    "content": ""
  },
  {
    "path": "wadl/src/test/resources/invalid_input/syntax_error.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  ources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\"\n        <request>\n          <param name=\"tag\" type=\"xsd:string\" style=\"query\" required=\"false\"/>\n          <param name=\"limit\" type=\"xsd:unsignedInt\" style=\"query\" required=\"true\"/>\n        </request>\n        <response status=\"200\">\n          <representation mediaType=\"application/json\"/>\n        </response>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/invalid_input/whitespaces_only_file.wadl",
    "content": "                                  "
  },
  {
    "path": "wadl/src/test/resources/matrix_parameters.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <request>\n          <param name=\"tag\" type=\"xsd:string\" style=\"matrix\" required=\"true\"/>\n          <param name=\"done\" type=\"xsd:boolean\" style=\"matrix\" required=\"false\"/>\n        </request>\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/path_parameters.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos/{id}\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <request>\n          <param name=\"id\" type=\"xsd:string\" style=\"template\" required=\"true\"/>\n        </request>\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/produces/produces_media_types_not_taken_from_consumes.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <request>\n          <representation mediaType=\"application/json\"/>\n          <representation mediaType=\"application/xml\"/>\n          <representation mediaType=\"text/plain\"/>\n        </request>\n        <response status=\"200\" />\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/produces/produces_no_media_types.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\" />\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/produces/produces_three_media_types.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <response status=\"200\">\n          <representation mediaType=\"application/json\"/>\n          <representation mediaType=\"application/xml\"/>\n          <representation mediaType=\"text/plain\"/>\n        </response>\n      </method>\n    </resource>\n  </resources>\n</application>"
  },
  {
    "path": "wadl/src/test/resources/query_parameters.wadl",
    "content": "<application xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://wadl.dev.java.net/2009/02\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns=\"http://wadl.dev.java.net/2009/02\">\n  <resources base=\"http://api.example.com/v1\">\n    <resource path=\"/todos\">\n      <method name=\"GET\" id=\"getAllTodos\">\n        <request>\n          <param name=\"tag\" type=\"xsd:string\" style=\"query\" required=\"false\"/>\n          <param name=\"limit\" type=\"xsd:unsignedInt\" style=\"query\" required=\"true\"/>\n        </request>\n        <response status=\"200\"/>\n      </method>\n    </resource>\n  </resources>\n</application>"
  }
]