Coder Social home page Coder Social logo

codecentric / hikaku Goto Github PK

View Code? Open in Web Editor NEW
198.0 8.0 19.0 799 KB

A library that tests if the implementation of a REST-API meets its specification.

License: Apache License 2.0

Kotlin 99.12% RAML 0.68% Shell 0.20%
openapi spring-mvc rest-api wadl rest restful-api restapi spring raml-test raml

hikaku's Introduction

hikaku

Build Status Maven Central Version

Hikaku (ๆฏ”่ผƒ) is japanese and means "comparison". This library tests if a REST-API implementation meets its specification.

If 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. The 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

Currently supported

Please refer to the list of all features. To check the feature support for each converter. It is possible that not every converter supports every feature. Only the intersection of the features of two EndpointConverters is used for the matching. Please keep that in mind regarding the equality of implementation and specification.

Usage

Setting 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. Then you call match() on the Hikaku class. The match result is sent to one or multiple Reporter. If the test fails kotlin's DefaultAsserter.fail() method is called.

Example

There 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. First add the dependencies for the converters, that we want to use. In this case hikaku-openapi and hikaku-spring.

dependencies {
    testImplementation "de.codecentric.hikaku:hikaku-openapi:$hikakuVersion"
    testImplementation "de.codecentric.hikaku:hikaku-spring:$hikakuVersion"
}

Kotlin

And now we can create the test case:

@SpringBootTest
class SpecificationTest {

    @Autowired
    private lateinit var springContext: ApplicationContext

    @Test
    fun `specification matches implementation`() {
        Hikaku(
                specification = OpenApiConverter(Paths.get("openapi.yaml")),
                implementation = SpringConverter(springContext),
                config = HikakuConfig(
                        filters = listOf(SpringConverter.IGNORE_ERROR_ENDPOINT)
                )
        )
        .match()
    }
}

Java

Same example in Java:

@SpringBootTest
public class SpecificationTest {

  @Autowired
  private ApplicationContext springContext;

  @Test
  public void specification_matches_implementation() {
    List<Function1<Endpoint, Boolean>> filters = new ArrayList<>();
    filters.add(SpringConverter.IGNORE_ERROR_ENDPOINT);

    List<Reporter> reporters = new ArrayList<>();
    reporters.add(new CommandLineReporter());

    new Hikaku(
            new OpenApiConverter(Paths.get("openapi.json")),
            new SpringConverter(springContext),
            new HikakuConfig(
                    reporters,
                    filters
            )
    )
    .match();
  }
}

Limitations

Hikaku 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.

http status codes

For 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.

Request and response object

For 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.

More Info

hikaku's People

Contributors

cc-jhr avatar dependabot[bot] avatar iazel avatar lmller avatar uuf6429 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hikaku's Issues

Support Spring Webflux

Is your feature request related to one or multiple existing converters?
Spring(Webflux?)Converter

Describe the solution you'd like
I'd like to see Spring Webflux among the supported converters. Webflux is based on the Spring Reactive concept, which is merely used for non-blocking implementations of RESTful services.
For a user it should be as easy to test his API against an openAPI spec for Spring Webflux as it is for Spring MVC.

Additional context
See here for Spring Reactive: https://spring.io/reactive

Personal Comment
I'd like to try to implement this feature myself, so I would be glad for any advice given ๐Ÿ‘

Tests for JaxRsConverter and MicronautConverter fail on windows machine

I've cloned the project on a windows machine using gitbash and executed the tests via command line.
The tests for micronaut and jax-rs are failing.
This probably relates to the code that searches for classes within the project. (That's why I labeled core as well).

I have not checked whether or not this would be the same result for a hikaku based tests using one of the mentioned converters.

Cannot locate classes with javax.ws.rs.Path

Setup information

hikaku version:
3.2.0

specification converter:
OpenAPI

implementation converter:
JAX-RS

build tool and version:
maven 3.6.3

Describe the bug

I'm trying to use Hikaku with Quarkus (1.12.2.Final). Quarkus uses the javax.ws.rs package instead of jakarta.ws.rs. When using de.codecentric.hikaku.converters.jaxrs.JaxRsConverter the ClassLocator cannot find any Paths.
I also cannot override JaxRsConverter because its set final by kotlins default.

Expected behavior

Find classes with javax.ws.rs.Path as well as jakarta.ws.rs.Path annotations.

Spring endpoints not discovered, `RequestMappingInfo.patternsCondition` returns null

Setup information

hikaku version: 3.3.0
specification converter: OpenAPI
implementation converter: Spring
build tool and version: Gradle 7.4.2
test framework: JUnit 5.8

Spring Boot 2.6.6, Spring WebMVC: 5.3.18

Describe the bug

I've copied the test from the README, but I get this error

๐Ÿ‘€ Expected, but unable to find:
<list of all endpoints>

internal fun RequestMappingInfo.paths(): Set<String> {
return this.patternsCondition?.patterns ?: emptySet()
}

I've stepped through the code and I can see that patternsCondition returns null. In the Javadoc I see:

This is mutually exclusive with {@link #getPathPatternsCondition()}
such that when one returns {@code null} the other one returns an instance.

I can see pathPatternsCondition seems to return the endpoint correctly.

Expected behavior

Hikaku can discover the endpoints defined in Spring

Code samples

The rest controllers are defined like this

import org.springframework.http.MediaType.APPLICATION_JSON_VALUE
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/my-api")
class MyRestController {

    @GetMapping(
        value = ["/some/endpoint"],
        produces = [APPLICATION_JSON_VALUE]
    )
    fun getDetails(
        id: String
    ): ResponseEntity<ResponseModel> {
        //...
    }
}

Evaluate possibility to check response objects

It would be beneficial to check the structural equality of data transfer objects (DTO) as well.

  • Check possibilites to retrieve that data throughout existing converters
  • Brainstorm hikaku internal presentation or data structure
  • Think about ways to present results in CommandLineReporter

Will ktor be supported by Hikaku?

Hi, thanks for providing this library, it made open api spec testing with spring boot much easier.

I was wondering if there will be ktor support in the future. I have found some commits by @cc-jhr that are related but it looks like they never made it to the master branch.

Are there any specific problems or complications to implement ktor support for hikaku? Anything the community could help with?

Cheers,
Stefan

Allow undeclared endpoints

Is your feature request related to one or multiple existing converters?
OpenAPI

Describe the solution you'd like
Allow tests to pass so long as the endpoints declared in your application contain all of the endpoints declared in the specification.

This differs from the current apparent behavior in that endpoints declared by your application but not in your spec will be allowed. This could be enabled with a flag.

Add list of responses for OpenApiConverter

Affects: OpenApiConverter

I would like to assert whether an endpoint contains one of responses as stated in a contract (at least status codes).

Proposed solution:
Endpoint class would contain additional property: responses/response. Add additional "extractor" to perform extraction of responses/response.

Support equals if content type matches and ignore charset

Setup information
hikaku version: 2.0.0-SNAPSHOT
specification converter: OpenApiConverter
implementation converter: SpringConverter

Describe the bug
When the API specification states application/json as content type byt the implementation return application/json;charset=UTF-8 they are not treated as equals. I am not sure if this is bug or maybe more a feature request (and there seems only be a bug template here), but if the implementation fullfills a contract the match should be OK.

Expected behavior
IMHO application/json;charset=UTF-8 is a valid implementation when application/json is required and should not be reported as an error.

Fix linux build

The travis linux build started failing.
It seems there has been an update on travis site. The dist hasn't been configured by us and changed from trusty to xenial. See the respective build logs:

first_failure.log
last_success.log

Other builds might fail, because trying to download from maven central might result in

Received status code 403 from server: Forbidden

Query Parameter based on an object

Is your feature request related to one or multiple existing converters?
SpringConverter

Describe the solution you'd like
Spring allows query parameter definitions by simply passing an object.

On extracting query parameters every controller method should be check for parameters (objects, not interfaces) without any spring annotation. The limitation to the usual spring controller method annotations is important, because the parameter could have a JSR-303 annotation or the like.

Easiest way to to get on all properties without having to do the reflection manually might be to serialize the type as json and and then extract the paths from the json. Suggestion for seriallization lib could be klaxon or moshi

Unchecked:

  • How do primitives such as String, Int, Long etc behave?

Additional context
Simple objects

data class Params1 (
  var a: String
  var b: String
)

data class Params2 (
  var a: String
  var c: String
)

@GetMapping("/todos")
fun getAllTodos(params1: Params1, params2 Params2) {
  /*
    calling: /todos?a=val1&b=val2&c=val3

    will result in :
    Params1(a = val1, b = val2)
    Params2(a = val1, c = val3)

  */
}

Nested object

data class Params1 (
  var a: String
  var b: Params2
)

data class Params2 (
  var a: String
  var c: String
)

@GetMapping("/todos")
fun getAllTodos(params1: Params1) {
  /*
    calling: /todos?a=val1&b.c=nestedvalue&c=othervalue

    will result in:
    Params1(a = val1, b = null)
    Params2(a = null, c = nestedvalue)

  */
}

Extract query parameter names from json:

{
  "a": null,
  "b": {
      "a": null,
      "c": null
    }
}

Must result in three query parameters:

  • a
  • b.a
  • b.c

Getting exception `Retrieving groups by name is not supported on this platform`

Setup information

java version: 11
hikaku version: 2.1.0
build tool and version: maven 3.5.4
test framework: junit 4.12

Describe the bug

Running the following test

    @Test
    public void testApi() throws URISyntaxException {
        final HikakuConfig config = new HikakuConfig(Set.of(SpringConverter.IGNORE_ERROR_ENDPOINT));
        final Path path = Paths.get(getClass().getClassLoader().getResource("openapi.yml").toURI());
        new Hikaku(new OpenApiConverter(path), new SpringConverter(applicationContext), config).match();
    }

Expected behavior

API matching test result

Actual result

Exception stacktrace:

de.codecentric.hikaku.converters.EndpointConverterException: Retrieving groups by name is not supported on this platform.

	at de.codecentric.hikaku.converters.openapi.OpenApiConverter.convert(OpenApiConverter.kt:45)
	at de.codecentric.hikaku.converters.AbstractEndpointConverter$conversionResult$2.invoke(AbstractEndpointConverter.kt:11)
	at de.codecentric.hikaku.converters.AbstractEndpointConverter$conversionResult$2.invoke(AbstractEndpointConverter.kt:8)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at de.codecentric.hikaku.converters.AbstractEndpointConverter.getConversionResult(AbstractEndpointConverter.kt)
	at de.codecentric.hikaku.Hikaku.match(Hikaku.kt:39)
	at com.example.Api_IT.testApi(Api_IT.java:30)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.UnsupportedOperationException: Retrieving groups by name is not supported on this platform.
	at kotlin.internal.jdk8.JDK8PlatformImplementations.getMatchResultNamedGroup(JDK8PlatformImplementations.kt:28)
	at kotlin.text.MatcherMatchResult$groups$1.get(Regex.kt:259)
	at kotlin.text.jdk8.RegexExtensionsJDK8Kt.get(RegexExtensions.kt:33)
	at de.codecentric.hikaku.converters.openapi.extractors.QueryParameterExtractor.extractQueryParametersFromComponents(QueryParameterExtractor.kt:32)
	at de.codecentric.hikaku.converters.openapi.extractors.QueryParameterExtractor.invoke(QueryParameterExtractor.kt:13)
	at de.codecentric.hikaku.converters.openapi.OpenApiConverter.parseOpenApi(OpenApiConverter.kt:65)
	at de.codecentric.hikaku.converters.openapi.OpenApiConverter.convert(OpenApiConverter.kt:43)
	... 36 more

Tests for ClassLocator

ClassLocator in core doesn't have any tests yet.

+Cases:+

  • empty package
  • classes on root level
  • classes in a nested path
  • class in nested path along as well as an empty package

Support google-style custom methods api paths

Is your feature request related to one or multiple existing converters?
Affects SpringConverter.

Describe the solution you'd like
Extend SpringConverter to support google-style custom methods api such as /v1/some/resource/name:customVerb. For more info please take a look at their documentation.

As of version 3.3.0, endpoints such as /todos/some:action are parsed as /todos/some}.

Additional context
As a sample of what would the change look like I created pull request #151. PTAL.

Thanks!

Add statement about of Pageable to documentation

Setup information
hikaku version: 2.0.0-SNAPSHOT
implementation converter: SpringConverter

Describe the bug
Spring data supports the idea of Pageable. A pageable is an object build by request parameter, supporting page, size and sort (parameter names are changeable). These parameters might be part of an api, but are not explizit mapped to query parameter. The documentation says "Query Parameter based on an object" are not supported, but I think a Pageable should be mentioned explizitly.

Expected behavior
Add support for Pageable or add a note that Pageable are currently not supported in hikaku.

Code samples:
Can you provide specifications or code snippets?

public ResponseEntity<Person> getPersons(
        @RequestParam(name = "language", required = false) String language,
        @PageableDefault Pageable pageable) {
...
}

Fix endpoints with HttpServletResponse parameters causing empty produces

Setup information

hikaku version: 2.2.0
specification converter: OpenApi
implementation converter: Spring
build tool and version: gradle 5, kotlin 1.3.21
test framework: junit 5.1

Describe the bug

Modifying response passed as method parameter (and thus not requiring a method return type) causes Hikaku to ignore produces in @XXXMapping annotation.

Expected behavior

Hikaku Spring converter should probably check that result is not void and there is no parameter of type HttpServletResponse.

Code samples

The following PoC produces this issue:

    @GetMapping("v1/test", produces = ["application/pdf"])
    fun invoke(response: HttpServletResponse)
    {
        try {
            val inputStream = fileStreamer.stream("s3://some-endpoint/test.pdf")
            IoUtils.copy(inputStream, response.outputStream)
        } catch (ex: NoSuchKeyException) {
            response.status = 404
        }
    }

The root cause is the this.value.method.hasNoReturnType() part here:
https://github.com/codecentric/hikaku/blob/master/spring/src/main/kotlin/de/codecentric/hikaku/converters/spring/extensions/ProducesSpringExtension.kt#L20

    if (isNotErrorPath && ((hasNoResponseBodyAnnotation && hasNoRestControllerAnnotation) || this.value.method.hasNoReturnType())) {
        return emptySet()
    }

Potential solution

Off the top of my mind, this might fix the problem:

    val isNotErrorPath = !this.key.patternsCondition.patterns.contains("/error")
    val hasNoResponseBodyAnnotation = !this.value.providesResponseBodyAnnotation()
    val hasNoRestControllerAnnotation = !this.value.providesRestControllerAnnotation()
    val hasHttpServletResponseParam = this.value.hasHttpServletResponseParam()

    if (isNotErrorPath && (hasNoResponseBodyAnnotation && hasNoRestControllerAnnotation)) {
        return emptySet()
    }

    if (isNotErrorPath && (this.value.method.hasNoReturnType() && !hasHttpServletResponseParam)) {
        return emptySet()
    }

    // ...

    private fun HandlerMethod.hasHttpServletResponseParam() = this.methodParameters
        .any { it.parameterType.isAssignableFrom(HttpServletResponse::class.java) }

Base API path not considered

Setup information

hikaku version: 3.1.2
specification converter: OpenAPI
implementation converter: Spring MVC

Describe the bug

Hikaku looks for the endpoint PUT /{id}.

Expected behavior

Hikaku will look for the endpoint PUT /api/rest/v1/{id}, prepending the base path of the server URL.
The OpenAPI Generator generator project uses the base path as the controller's @RequestMapping by default.

Code samples

Can you provide specification snippets or code snippets?

openapi: 3.0.1
info:
  title: Badgr Pro APIs
  version: v1
servers:
- url: http://server.com/api/rest/v1
  description: API
paths:
  /{id}:
    put:
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
                 type: string
      responses:
        200:
          description: success

ResponseEntity<Unit> produces 'application/json'

Setup information

hikaku version: 3.1.2
specification converter: OpenAPI
implementation converter: Spring MVC

Describe the bug

Methods that return ResponseEntity<Unit> are assumed to produce 'application/json' content.

Expected behavior

ResponseEntity<Unit> should be interpreted in the same way as if the method had no return type. It should not be considered to produce content of any type.

Code samples

Kotlin

@RestController
@Validated
@RequestMapping("")
class Controller {


    @RequestMapping(
        value = ["/api/rest/v1/{id}"],
        consumes = ["application/json"],
        method = [RequestMethod.PUT])
    fun updateIssuerOrganization( @PathVariable("id") id: kotlin.String
, @Valid @RequestBody body: kotlin.String?
): ResponseEntity<Unit> {
        return ResponseEntity.ok().build()
    }
}

Unable to get code running on OpenJDK 11

Setup information

hikaku version: 3.0.0
specification converter: OpenApiConverter
implementation converter: SpringConverter
build tool and version: gradle-5.6.2
test framework: SpockFramework

Describe the bug

Hikaku is unable to run test using Java 11

hikaku.match()
|      |
|      de.codecentric.hikaku.converters.EndpointConverterException: Retrieving groups by name is not supported on this platform.
|      	at de.codecentric.hikaku.converters.openapi.OpenApiConverter.convert(OpenApiConverter.kt:46)
|      	at de.codecentric.hikaku.converters.AbstractEndpointConverter$conversionResult$2.invoke(AbstractEndpointConverter.kt:11)
|      	at de.codecentric.hikaku.converters.AbstractEndpointConverter$conversionResult$2.invoke(AbstractEndpointConverter.kt:8)
|      	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
|      	at de.codecentric.hikaku.Hikaku.match(Hikaku.kt:41)
|      	at com.kws.cultivent.fieldservice.FieldManagementApiIntegrationTest.Check IMPLEMENTATION and SPECIFICATION(FieldManagementApiIntegrationTest.groovy:67)
|      Caused by: java.lang.UnsupportedOperationException: Retrieving groups by name is not supported on this platform.
|      	at kotlin.internal.jdk8.JDK8PlatformImplementations.getMatchResultNamedGroup(JDK8PlatformImplementations.kt:28)
|      	at kotlin.text.MatcherMatchResult$groups$1.get(Regex.kt:259)
|      	at kotlin.text.jdk8.RegexExtensionsJDK8Kt.get(RegexExtensions.kt:33)
|      	at de.codecentric.hikaku.converters.openapi.extractors.QueryParameterExtractor.extractQueryParametersFromComponents(QueryParameterExtractor.kt:30)
|      	at de.codecentric.hikaku.converters.openapi.extractors.QueryParameterExtractor.invoke(QueryParameterExtractor.kt:12)
|      	at de.codecentric.hikaku.converters.openapi.OpenApiConverter.parseOpenApi(OpenApiConverter.kt:70)
|      	at de.codecentric.hikaku.converters.openapi.OpenApiConverter.convert(OpenApiConverter.kt:44)
|      	... 5 more

Expected behavior

Code should work in the same way as on JDK 8 or any idea for a workaround

Code samples

Can you provide specification snippets or code snippets?

new Hikaku(
        openApiConverter,
        springConverter,
        hikakuConfig
      ).match()

Remove constructor awaiting a String

WADL and OpenAPI converter provide a constructor awaiting the String. But the String is not the path of the file specification file, but the whole specification as a String which is misleading.

Parameter referenced from components are not detected

Setup information
hikaku version: 1.1.0
specification converter: OpenApiConverter
implementation converter: SpringConverter
build tool and version gradle
test framework spock

Describe the bug
In my OpenAPI specification I have described parameter like the following in the path sectio

parameters:
        - $ref: "#/components/parameters/tenantParam"
        - name: qrCode
          in: query
          example: 0101234567890123sd0DE012-1234567-xyz
          description: The qr code 
          schema:
            type: string

In the parameter section tenantParam is described as

    tenantParam:
      name: tenant
      in: query
      description: The tenant of a user
      schema:
        $ref: "#/components/schemas/Tenant"
      example: de

And the schema as

    Tenant:
      type: string
      minLength: 2
      maxLength: 2
      example: de

While the qrCode parameter is checked as expected the tenant parameter is shown as Unexpected but found and not listed in the report.

Expected behavior
Parmeters should be handled the same when added directly in the param section as when a reference is used. The same seems to happen with all other referenced parameters.

Code samples:
Can you provide specifications or code snippets?

  def "Check implementation vs specification of api"() {
    given:
      def path = Paths.get("../spec/my-api.yaml")
      OpenApiConverter openApiConverter = OpenApiConverter.usingPath(path);
      SpringConverter springConverter = new SpringConverter(springContext);

      HikakuConfig hikakuConfig = new HikakuConfig(
        [SpringConverter.IGNORE_ERROR_ENDPOINT] as Set,
        true,
        true
      );

    when:
      def hikaku = new Hikaku(
        openApiConverter,
        springConverter,
        hikakuConfig
      )
    then:
      hikaku.match();
  }

Wrong file encoding leads to unclear error message

Setup information
hikaku version: 1.1.1 (probably also in 2.0.0)
specification converter: OpenApi
OS: Windows 7 Enterprise

Describe the bug
If the open api specification file (e.g. openapi.json) is is read with other encoding than UTF-8 (happens on windows, apparently), then the following line in the OpenApiConverter results in an error, because openApi will be null:

 val openApi = OpenAPIV3Parser().readContents(specificationContent, null, null).openAPI

Though the encoding error is expected, it is shadowed by an IllegalStateException thrown by the illegal null access. The encoding error is not an exception, but a message inside the SwaggerParseResult

Expected behavior
The encoding error should be presented to the user.

Support OpenAPI 3.1

Describe the solution you'd like

I have an OpenAPI spec version 3.1.

I'd like to use hikaku with it, but when I do, it fails without a clear error message. I changed the OpenAPI spec to say it was version 3.0.3, and it works without issue.

Spring Redirect Enpoint : produces attribute not empty

Setup information

hikaku version: 3.0.0
specification converter: OpenApiConverter
implementation converter: SpringConverter
build tool and version: gradle 5.6.4
test framework: junit5

Describe the bug

Hi,
we have a problem with Spring endpoints which must return a redirect URL (status 302 or 301).
When we run the Hikaku test, Hikaku generate a "produces" attribute for this endpoint, and so the test fail because our OpenApi Endpoint doesn't have a content.

This generation of produces attribute is in the ProducesSpringExtension, and for now, to have a empty produces, the endpoint have to respect one of these condition :

  • no return and no HttpServletResponseParam and no error in path
  • no @responsebody and no @RestController and no error in path
    In other case, it used the produces (if it's present) or put a default produces

Expected behavior

When endpoint :

  • return a "RedirectView" or
  • method has a param HttpServletResponse and no return
    Then ProducesSpringExtension return the produces attribute define in the endpoint.

N.B. : when we do a redirect with the HttpServletResponse, we don't have to specify a @ResponseStatus but this is the only way I think to differentiate in the ProducesSpringExtension a Redirect from another status

Code samples

Sample of the current bug

@GetMapping("/github")
    fun redirectToGithub(): RedirectView {
        return RedirectView("https://github.com/codecentric/hikaku")
    }

//or with the HttpServletReponse
@GetMapping("/github")
fun redirectToGithub(response: HttpServletResponse) {
        response.sendRedirect("https://github.com/codecentric/hikaku")
    }

I can if you want suggest a PR.

Allow to disable adding the HEAD and OPTIONS endpoints automatically in the Spring Converter

Is your feature request related to one or multiple existing converters?
AFAICS only the Spring Converter is affected.

Describe the solution you'd like
I would like for the HikakuConfig to accept a feature flag that disables the implicit/automatic addition of HEAD and OPTIONS endpoints.

Additional context
I have never seen an OpenAPI contract in the wild that documented the HEAD and OPTIONS endpoints explicitly. Yet, if I don't I can't validate my implementation with hikaku. HikakuConfig#filters are not the correct approach IMO to solve this as I can't distinguish in my filter implementation whether a given HEAD/OPTIONS endpoint is an organic one or one that was added by hikaku.

Endpoints provide default media type for 'produces' if there is no return type

Setup information
hikaku version: 1.1.1
specification converter: -
implementation converter: SpringConverter
build tool and version: gradle 5.2.1
test framework: junit 5.4.0

Describe the bug
If you use @RestController annotation and a controller method does not provide a return type, then the resulting endpoint lists the default media type for produces.

Expected behavior
Produces list should be empty.

Code samples:
Can you provide specifications or code snippets?

@RestController
@RequestMapping("/todos")
class TodosController {

    @RequestMapping(method = [POST])
    fun createTodo(@RequestBody todo: Todo) { }
}

Split into separate gradle modules

The plan is to add more frameworks. In order to bring the minimum amount of dependencies into the projects we should split the project into a core simply called 'hikaku' containing

de.codecentric.hikaku.Hikaku
de.codecentric.hikaku.HikakuConfig
de.codecentric.hikaku.SupportedFeatures
de.codecentric.hikaku.reporter.*
de.codecentric.hikaku.converter.EndpointConverter
de.codecentric.hikaku.converter.AbstractEndpointConverter

Then there should be one gradle module for each supported EndpointConverter
hikaku-spring, hikaku-openapi, hikaku-wadl

Add CI

Integrate a CI that supports github PR checks.

Response media type is not extracted for @RestController annotation

Setup information
hikaku version: 1.1.0
specification converter: -
implementation converter: SpringConverter
build tool and version: gradle 5.2.1
test framework: junit 5.4.0

Describe the bug
Extracting the response media type is done by checking the @ResponseBody annotation. This is fine for @Controller annotation in combination with @ResponseBody. The @RestControllerannotation combines both already. So in this case the response media type couldn't be extracted.

Expected behavior
Media type is extracted for both cases:

  • @Controller in combination with @ResponseBody
  • @RestController

Code samples:
Can you provide specifications or code snippets?

@Controller
@ResponseBody
open class GetMappingOneMediaTypeIsExtractedCorrectlyController {

    @GetMapping("/todos", produces = [APPLICATION_XML_VALUE])
    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingOneMediaTypeIsExtractedCorrectlyController())
}
@RestController
open class GetMappingOneMediaTypeIsExtractedCorrectlyController {

    @GetMapping("/todos", produces = [APPLICATION_XML_VALUE])
    fun getAllTodos() = ResponseEntity.status(200).body(GetMappingOneMediaTypeIsExtractedCorrectlyController())
}

Support multiple Reporter

At the moment it is only possible to send the MatchResult to exactly one Reporter.
It would be nice to be able to add a number of Reporters to the HikakuConfig to be able to combine them and send the MatchResult to them all.

Regex error in regex replacement

Setup information

hikaku version: 3.1.2
specification converter:
implementation converter: SpringConverter (in hikaku-spring)
build tool and version: maven 3.x
test framework: junit 5.x

Describe the bug

I think the removeRegex method in SpringConverter has some issue on path patterns replacement, the regex does not work as expected.

Expected behavior

When a path of the form {resource:regex}, example when RequestMapping.value is the format/{sending_id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}, the regex is not removed as expected and returns /{sendings}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}, rather than /{sendings}.

Suggestion

I think the regex should be replaced with

private fun removeRegex(path: String): String {
    if (path.contains(':')) {
        return path.replace(Regex(":.*"), "}")
    }

    return path
}

Support JAX-RS 2

Hopefully implement in a way to be able to support jersey, cxf, restlet and resteasy with only one module.

Add windows CI build

Currently the tests for hikaku are run in travis on linux with openjdk 8 and 11.
As of #38 I think it makes sense to add windows as well.

See also this comment in #38 (comment)

Failed to get the implementation on Spring MVC 5.3.18

Setup information

hikaku version: 3.3.0
specification converter: OpenApiConverter
implementation converter: SpringConverter
build tool and version: gradle 6.8.01
test framework: junit-pioneer 1.6.2

Describe the bug

SpringConverter fails to get the Application endpoints

Expected behavior

SpringConverter can get the Application endpoints

Code samples

Can you provide specification snippets or code snippets?

CODE HERE

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.