Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions end2end-tests/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
val fabrikt: Configuration by configurations.creating

val generationDir = "$buildDir/generated"
val apiFile = "$buildDir/../../src/test/resources/examples/okHttpClient/api.yaml"
val apiFile = "$buildDir/../../src/test/resources/examples/httpClient/api.yaml"

sourceSets {
main { java.srcDirs("$generationDir/src/main/kotlin") }
Expand Down Expand Up @@ -40,7 +40,7 @@ dependencies {

tasks {

val generateCode by creating(JavaExec::class) {
val generateOkioCode by creating(JavaExec::class) {
inputs.files(apiFile)
outputs.dir(generationDir)
outputs.cacheIf { true }
Expand All @@ -58,9 +58,29 @@ tasks {
dependsOn(":shadowJar")
}

val generateJdkClientCode by creating(JavaExec::class) {
inputs.files(apiFile)
outputs.dir(generationDir)
outputs.cacheIf { true }
classpath = rootProject.files("./build/libs/fabrikt-${rootProject.version}.jar")
mainClass.set("com.cjbooms.fabrikt.cli.CodeGen")
args = listOf(
"--output-directory", generationDir,
"--base-package", "com.example.jdk_client",
"--api-file", apiFile,
"--targets", "http_models",
"--http-client-target", "JDK_HTTP",
"--targets", "client",
"--http-client-opts", "resilience4j"
)
dependsOn(":jar")
dependsOn(":shadowJar")
}

withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = "17"
dependsOn(generateCode)
dependsOn(generateOkioCode)
dependsOn(generateJdkClientCode)
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
package com.cjbooms.fabrikt.clients.jdk

import com.example.jdk_client.client.ApiClientException
import com.example.jdk_client.client.ApiRedirectException
import com.example.jdk_client.client.ApiServerException
import com.example.jdk_client.client.ExamplePath2Client
import com.example.jdk_client.client.ExamplePath3SubresourceClient
import com.example.jdk_client.client.ExamplePath1Client
import com.example.jdk_client.models.Failure
import com.example.jdk_client.models.FirstModel
import com.example.jdk_client.models.QueryResult
import com.fasterxml.jackson.databind.ObjectMapper
import com.github.tomakehurst.wiremock.WireMockServer
import com.github.tomakehurst.wiremock.common.ConsoleNotifier
import com.github.tomakehurst.wiremock.core.WireMockConfiguration
import com.marcinziolo.kotlin.wiremock.*
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.*
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import java.net.ServerSocket
import java.net.http.HttpClient
import java.util.*
import java.util.stream.Stream

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class JdkTest {
private val port: Int = ServerSocket(0).use { socket -> socket.localPort }

private val wiremock: WireMockServer = WireMockServer(
WireMockConfiguration.options().port(port).notifier(
ConsoleNotifier(true)
))

private val mapper = ObjectMapper()
private val httpClient = HttpClient.newHttpClient()
private val examplePath1Client = ExamplePath1Client(mapper, "http://localhost:$port", httpClient)
private val examplePath2Client = ExamplePath2Client(mapper, "http://localhost:$port", httpClient)
private val examplePath3Client = ExamplePath3SubresourceClient(mapper, "http://localhost:$port", httpClient)

private val uuid = UUID.randomUUID()
private val failure = Failure(traceId = uuid,
error = "testError",
errorCode = "testErrorCode")

@Suppress("unused")
private fun path2ErrorCodes(): Stream<Int> = Stream.of(400, 422, 423)

@BeforeEach
fun setUp() {
wiremock.start()
}

@AfterEach
fun afterEach() {
wiremock.resetAll()
wiremock.stop()
}

@Test
fun `throws an exception if 404 is returned`() {
wiremock.get {
url like "/example-path-1"
} returns {
statusCode = 404
}

val result = assertThrows<ApiClientException> {
examplePath1Client.getExamplePath1()
}
Assertions.assertThat(result.statusCode).isEqualTo(404)
}

@Test
fun `returns data when no query parameters are send`(testInfo: TestInfo) {
wiremock.get {
url like "/example-path-1"
} returns {
statusCode = 200
body = mapper.writeValueAsString(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

val result = examplePath1Client.getExamplePath1()

Assertions.assertThat(result.data).isEqualTo(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

@Test
fun `adds query_param2 to the query`(testInfo: TestInfo) {
wiremock.get {
urlPath like "/example-path-1"
queryParams contains "query_param2" like "10"
} returns {
statusCode = 200
body = mapper.writeValueAsString(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

val result = examplePath1Client.getExamplePath1(queryParam2 = 10)

Assertions.assertThat(result.data).isEqualTo(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

@Test
fun `adds explode_list_query_param to the query`(testInfo: TestInfo) {
wiremock.get {
urlPath like "/example-path-1"
queryParams contains "explode_list_query_param" like "list"
queryParams contains "explode_list_query_param" like "of"
queryParams contains "explode_list_query_param" like "parameters"
} returns {
statusCode = 200
body = mapper.writeValueAsString(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

val result = examplePath1Client.getExamplePath1(explodeListQueryParam = listOf("list", "of", "parameters"))

Assertions.assertThat(result.data).isEqualTo(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

@Test
fun `adds additional headers to the query`(testInfo: TestInfo) {
wiremock.get {
urlPath like "/example-path-1"
headers contains "awesome" like "header"
} returns {
statusCode = 200
body = mapper.writeValueAsString(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

val result = examplePath1Client.getExamplePath1(additionalHeaders = mapOf("awesome" to "header"))

Assertions.assertThat(result.data).isEqualTo(
QueryResult(
listOf(FirstModel(id = testInfo.displayName))
)
)
}

@Test
fun `send body with post request`(testInfo: TestInfo) {
val content = FirstModel(id = testInfo.displayName)
wiremock.post {
urlPath like "/example-path-1"
body equalTo mapper.writeValueAsString(content)
} returns {
statusCode = 201
}

val result = examplePath1Client.postExamplePath1(content)
Assertions.assertThat(result.statusCode).isEqualTo(201)
}

@ParameterizedTest
@MethodSource("path2ErrorCodes")
fun `throws an exception if a 4xx http status code is returned`(errorCode: Int) {
wiremock.get {
urlPath like "/example-path-2/$errorCode"
} returns {
statusCode = errorCode
body = mapper.writeValueAsString(failure)
}

val result = assertThrows<ApiClientException> {
examplePath2Client.getExamplePath2PathParam(errorCode.toString(), 10)
}

Assertions.assertThat(result.statusCode).isEqualTo(errorCode)
Assertions.assertThat(mapper.readValue(result.message, Failure::class.java)).isEqualTo(failure)
}

@Test
fun `throws an exception if a http status code 500 is returned`() {
wiremock.get {
urlPath like "/example-path-2/500"
} returns {
statusCode = 500
body = mapper.writeValueAsString(failure)
}

val result = assertThrows<ApiServerException> {
examplePath2Client.getExamplePath2PathParam("500", 10)
}

Assertions.assertThat(result.statusCode).isEqualTo(500)
Assertions.assertThat(mapper.readValue(result.message, Failure::class.java)).isEqualTo(failure)
}

@Test
fun `throws an exception if a http status code 304 is returned`() {
wiremock.get {
urlPath like "/example-path-2/304"
} returns {
statusCode = 304
}

val result = assertThrows<ApiRedirectException> {
examplePath2Client.getExamplePath2PathParam("304", 10)
}

Assertions.assertThat(result.statusCode).isEqualTo(304)
}


@Test
fun `head returns 200`() {
wiremock.head {
urlPath like "/example-path-2/head200"
} returns {
statusCode = 200
}

val result = examplePath2Client.headOperationIdExample("head200")

Assertions.assertThat(result.statusCode).isEqualTo(200)
}

@Test
fun `put returns 204`() {
val model = FirstModel(id = "put", secondAttr = "204")
wiremock.put {
urlPath like "/example-path-2/put204"
body equalTo mapper.writeValueAsString(model)
headers contains "If-Match" like "match"
} returns {
statusCode = 204
}

val result = examplePath2Client.putExamplePath2PathParam(firstModel = model, pathParam = "put204", ifMatch = "match")

Assertions.assertThat(result.statusCode).isEqualTo(204)
}

@Test
fun `put returns 204 with sub resource`() {
val model = FirstModel(id = "put", secondAttr = "304")
wiremock.put {
urlPath like "/example-path-3/put304/subresource"
body equalTo mapper.writeValueAsString(model)
headers contains "If-Match" like "match"
} returns {
statusCode = 204
}

val result = examplePath3Client.putExamplePath3PathParamSubresource(firstModel = model, pathParam = "put304", ifMatch = "match")

Assertions.assertThat(result.statusCode).isEqualTo(204)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.cjbooms.fabrikt.clients.jdk

import com.example.jdk_client.client.Url
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import java.net.URI

class UrlTest {

@Test
fun testExpansion() {
val url = Url("http://bla.blub/{a}/test/{b}")
.addPathParam("a", "123")
.addPathParam("b", "abc")
.addQueryParam("expand", "true")
.addQueryParam("whatever", "654")

assertThat(url.toUri())
.isEqualTo(URI.create("http://bla.blub/123/test/abc?expand=true&whatever=654"))
}

@Test
fun testWithoutQueryParams() {
val url = Url("http://bla.blub/{a}/test/{b}")
.addPathParam("a", "123")
.addPathParam("b", "abc")

assertThat(url.toUri())
.isEqualTo(URI.create("http://bla.blub/123/test/abc"))
}

@Test
fun testArrayWithoutExplode() {
val url = Url("http://bla.blub/test")
.addQueryParam("queryParam", listOf("a", "b"), true)

assertThat(url.toUri())
.isEqualTo(URI.create("http://bla.blub/test?queryParam=a&queryParam=b"))
}

@Test
fun testArrayWithExplode() {
val url = Url("http://bla.blub/test")
.addQueryParam("queryParam", listOf("a", "b"), false)

assertThat(url.toUri())
.isEqualTo(URI.create("http://bla.blub/test?queryParam=a,b"))
}
}
3 changes: 2 additions & 1 deletion src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGenOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ enum class ClientCodeGenOptionType(private val description: String) {

enum class ClientCodeGenTargetType(val description: String) {
OK_HTTP("Generate OkHttp client."),
OPEN_FEIGN("Generate OpenFeign client.");
OPEN_FEIGN("Generate OpenFeign client."),
JDK_HTTP("Generate JDK HTTP client.");

override fun toString() = "`${super.toString()}` - $description"
}
Expand Down
Loading