From 302d028c5bc71a8dd18a5d59d31b6a8dea49ff09 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 1 May 2020 16:47:38 +0800 Subject: [PATCH] Test scala akka petstore client in CI (#6118) * test scala akka in ci * fix compilation error * fix scala akka test * add tests --- bin/openapi3/scala-akka-petstore.sh | 2 +- .../languages/ScalaAkkaClientCodegen.java | 1 - .../resources/scala-akka-client/pom.mustache | 5 +- .../resources/3_0/scala-akka/petstore.yaml | 742 ++++++++++++++++++ pom.xml | 4 +- samples/client/petstore/scala-akka/pom.xml | 5 +- .../client/petstore/scala-akka/pom.xml | 5 +- .../org/openapitools/client/api/PetApi.scala | 2 + .../src/test/scala/PetApiTest.scala | 123 +++ 9 files changed, 879 insertions(+), 10 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/scala-akka/petstore.yaml create mode 100644 samples/openapi3/client/petstore/scala-akka/src/test/scala/PetApiTest.scala diff --git a/bin/openapi3/scala-akka-petstore.sh b/bin/openapi3/scala-akka-petstore.sh index 736fe0312464..5443c58f8fb7 100755 --- a/bin/openapi3/scala-akka-petstore.sh +++ b/bin/openapi3/scala-akka-petstore.sh @@ -27,6 +27,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate --artifact-id "scala-akka-petstore-client" -t modules/openapi-generator/src/main/resources/scala-akka-client -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g scala-akka -o samples/openapi3/client/petstore/scala-akka $@" +ags="generate --artifact-id "scala-akka-petstore-client" -t modules/openapi-generator/src/main/resources/scala-akka-client -i modules/openapi-generator/src/test/resources/3_0/scala-akka/petstore.yaml -g scala-akka -o samples/openapi3/client/petstore/scala-akka $@" java $JAVA_OPTS -jar $executable $ags diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaAkkaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaAkkaClientCodegen.java index 8f1bdde8c63f..c6da992792b9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaAkkaClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaAkkaClientCodegen.java @@ -35,7 +35,6 @@ import java.io.Writer; import java.util.*; -import static org.openapitools.codegen.languages.AbstractJavaCodegen.DATE_LIBRARY; import static org.openapitools.codegen.utils.StringUtils.camelize; public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements CodegenConfig { diff --git a/modules/openapi-generator/src/main/resources/scala-akka-client/pom.mustache b/modules/openapi-generator/src/main/resources/scala-akka-client/pom.mustache index 9162fce7a255..5f3f0aafdad3 100644 --- a/modules/openapi-generator/src/main/resources/scala-akka-client/pom.mustache +++ b/modules/openapi-generator/src/main/resources/scala-akka-client/pom.mustache @@ -136,7 +136,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 + 3.0.0-M4 @@ -146,6 +146,7 @@ -Xms512m -Xmx1500m methods + 4 pertest @@ -260,4 +261,4 @@ - \ No newline at end of file + diff --git a/modules/openapi-generator/src/test/resources/3_0/scala-akka/petstore.yaml b/modules/openapi-generator/src/test/resources/3_0/scala-akka/petstore.yaml new file mode 100644 index 000000000000..fe228bf44473 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/scala-akka/petstore.yaml @@ -0,0 +1,742 @@ +openapi: 3.0.0 +servers: + - url: 'http://petstore.swagger.io/v2' +info: + description: >- + This is a sample server Petstore server. For this sample, you can use the api key + `special-key` to test the authorization filters. + version: 1.0.0 + title: OpenAPI Petstore + license: + name: Apache-2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' +tags: + - name: pet + description: Everything about your Pets + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user +paths: + /pet: + post: + tags: + - pet + summary: Add a new pet to the store + description: '' + operationId: addPet + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + put: + tags: + - pet + summary: Update an existing pet + description: '' + operationId: updatePet + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + style: form + explode: false + schema: + type: array + items: + type: string + enum: + - available + - pending + - sold + default: available + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - 'read:pets' + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: >- + Multiple tags can be provided with comma separated strings. Use tag1, + tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: true + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - 'read:pets' + deprecated: true + '/pet/{petId}': + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + delete: + tags: + - pet + summary: Deletes a pet + description: '' + operationId: deletePet + parameters: + - name: api_key + in: header + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + '/pet/{petId}/uploadImage': + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + type: string + format: binary + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: '' + operationId: placeOrder + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid Order + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + '/store/order/{orderId}': + get: + tags: + - store + summary: Find purchase order by ID + description: >- + For valid response try integer IDs with value <= 5 or > 10. Other values + will generated exceptions + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of pet that needs to be fetched + required: true + schema: + type: integer + format: int64 + minimum: 1 + maximum: 5 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: >- + For valid response try integer IDs with value < 1000. Anything above + 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + responses: + default: + description: successful operation + security: + - auth_cookie: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + /user/createWithArray: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithArrayInput + responses: + default: + description: successful operation + security: + - auth_cookie: [] + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithListInput + responses: + default: + description: successful operation + security: + - auth_cookie: [] + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: true + schema: + type: string + pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$' + - name: password + in: query + description: The password for login in clear text + required: true + schema: + type: string + responses: + '200': + description: successful operation + headers: + Set-Cookie: + description: >- + Cookie authentication key for use with the `auth_cookie` + apiKey authentication. + schema: + type: string + example: AUTH_KEY=abcde12345; Path=/; HttpOnly + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when toekn expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + responses: + default: + description: successful operation + security: + - auth_cookie: [] + '/user/{username}': + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + parameters: + - name: username + in: path + description: The name that needs to be fetched. Use user1 for testing. + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Updated user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid user supplied + '404': + description: User not found + security: + - auth_cookie: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found + security: + - auth_cookie: [] +externalDocs: + description: Find out more about Swagger + url: 'http://swagger.io' +components: + requestBodies: + UserArray: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + type: apiKey + name: api_key + in: header + auth_cookie: + type: apiKey + name: AUTH_KEY + in: cookie + schemas: + Order: + title: Pet Order + description: An order for a pets from the pet store + type: object + properties: + id: + type: integer + format: int64 + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + enum: + - placed + - approved + - delivered + complete: + type: boolean + default: false + xml: + name: Order + Category: + title: Pet category + description: A category for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$' + xml: + name: Category + User: + title: a User + description: A User who is purchasing from the pet store + type: object + properties: + id: + type: integer + format: int64 + username: + type: string + firstName: + type: string + lastName: + type: string + email: + type: string + password: + type: string + phone: + type: string + userStatus: + type: integer + format: int32 + description: User Status + xml: + name: User + Tag: + title: Pet Tag + description: A tag for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Tag + Pet: + title: a Pet + description: A pet for sale in the pet store + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + xml: + name: tag + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: Pet + ApiResponse: + title: An uploaded response + description: Describes the result of uploading an image resource + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string diff --git a/pom.xml b/pom.xml index b9ff2c632c3d..6c02ecbf7ff5 100644 --- a/pom.xml +++ b/pom.xml @@ -1296,7 +1296,7 @@ samples/openapi3/client/petstore/go-experimental samples/openapi3/client/petstore/go - + samples/openapi3/client/petstore/scala-akka samples/openapi3/client/petstore/scala-sttp samples/client/petstore/scala-httpclient samples/client/petstore/scalaz @@ -1392,7 +1392,7 @@ samples/openapi3/client/petstore/ruby - + samples/openapi3/client/petstore/scala-akka samples/client/petstore/dart2/petstore samples/client/petstore/dart-jaguar/openapi samples/client/petstore/dart-jaguar/flutter_petstore/openapi diff --git a/samples/client/petstore/scala-akka/pom.xml b/samples/client/petstore/scala-akka/pom.xml index bd865860a90a..a88eaa5a41ef 100644 --- a/samples/client/petstore/scala-akka/pom.xml +++ b/samples/client/petstore/scala-akka/pom.xml @@ -126,7 +126,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 + 3.0.0-M4 @@ -136,6 +136,7 @@ -Xms512m -Xmx1500m methods + 4 pertest @@ -250,4 +251,4 @@ - \ No newline at end of file + diff --git a/samples/openapi3/client/petstore/scala-akka/pom.xml b/samples/openapi3/client/petstore/scala-akka/pom.xml index bd865860a90a..a88eaa5a41ef 100644 --- a/samples/openapi3/client/petstore/scala-akka/pom.xml +++ b/samples/openapi3/client/petstore/scala-akka/pom.xml @@ -126,7 +126,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 + 3.0.0-M4 @@ -136,6 +136,7 @@ -Xms512m -Xmx1500m methods + 4 pertest @@ -250,4 +251,4 @@ - \ No newline at end of file + diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala index df82ca29fca2..c0ba5d4c6ae2 100644 --- a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala +++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala @@ -127,6 +127,7 @@ class PetApi(baseUrl: String) { /** * Expected answers: + * code 200 : (successful operation) * code 405 : (Invalid input) * * @param petId ID of pet that needs to be updated @@ -138,6 +139,7 @@ class PetApi(baseUrl: String) { .withFormParam("name", name) .withFormParam("status", status) .withPathParam("petId", petId) + .withSuccessResponse[Unit](200) .withErrorResponse[Unit](405) diff --git a/samples/openapi3/client/petstore/scala-akka/src/test/scala/PetApiTest.scala b/samples/openapi3/client/petstore/scala-akka/src/test/scala/PetApiTest.scala new file mode 100644 index 000000000000..e6229fb05f3a --- /dev/null +++ b/samples/openapi3/client/petstore/scala-akka/src/test/scala/PetApiTest.scala @@ -0,0 +1,123 @@ +import akka.actor.ActorSystem +import org.junit.runner.RunWith +import org.openapitools.client._ +import org.openapitools.client.api._ +import org.openapitools.client.core.{ApiInvoker, ApiKeyValue} +import org.openapitools.client.model._ +import org.scalatest.Inspectors._ +import org.scalatest._ +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class PetApiTest extends AsyncFlatSpec with Matchers { + + private implicit val system: ActorSystem = ActorSystem() + + behavior of "PetApi" + val api: PetApi = PetApi() + val invoker: ApiInvoker = ApiInvoker(EnumsSerializers.all) + private implicit val apiKey: ApiKeyValue = ApiKeyValue("special-key") + + it should "add and fetch a pet" in { + val petId = 1000 + val createdPet = Pet( + Some(petId), + Some(Category(Some(1), Some("sold"))), + "dragon", + (for (i <- 1 to 10) yield "http://foo.com/photo/" + i).toList, + Some((for (i <- 1 to 5) yield org.openapitools.client.model.Tag(Some(i), Some("tag-" + i))).toList), + Some(PetEnums.Status.Sold) + ) + + val addPetRequest = api.addPet(createdPet) + val getPetRequest = api.getPetById(petId) + + for { + addResponse <- invoker.execute(addPetRequest) + response <- invoker.execute(getPetRequest) + } yield { + addResponse.code should be(200) + + response.code should be(200) + val pet = response.content + + pet should have( + 'id (createdPet.id), + 'status (createdPet.status), + 'category (createdPet.category), + 'name (createdPet.name) + ) + pet.tags should not be empty + pet.tags.get should contain theSameElementsInOrderAs createdPet.tags.get + pet.photoUrls should contain theSameElementsInOrderAs createdPet.photoUrls + } + } + + it should "update a pet" in { + val petId = (Math.random()*1000000000).toLong + val createdPet = Pet( + Some(petId), + Some(Category(Some(1), Some("sold"))), + "programmer", + (for (i <- 1 to 10) yield "http://foo.com/photo/" + i).toList, + Some((for (i <- 1 to 5) yield org.openapitools.client.model.Tag(Some(i), Some("tag-" + i))).toList), + Some(PetEnums.Status.Available) + ) + + for { + createdPet <- invoker.execute(api.addPet(createdPet)) + pet: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get)) + updatedPet = pet.content.copy(status = Some(PetEnums.Status.Sold), name = "developer") + updatedPetResponse: core.ApiResponse[Pet] <- invoker.execute(api.updatePet(updatedPet)) + updatedRequested: core.ApiResponse[Pet] <- invoker.execute(api.getPetById(createdPet.content.id.get)) + } yield { + pet.content.name should be("programmer") + pet.content.status should be(Some(PetEnums.Status.Available)) + + updatedPetResponse.content.name should be("developer") + updatedPetResponse.content.status should be(Some(PetEnums.Status.Sold)) + + updatedRequested.content.name should be("developer") + updatedRequested.content.status should be(Some(PetEnums.Status.Sold)) + + } + + } + + it should "find pets by status" in { + val request = api.findPetsByStatus(List("available")) + + invoker + .execute(request) + .map { apiResponse => + apiResponse.code should be(200) + val pets = apiResponse.content + pets should not be empty + + forAll(pets) { pet => + pet.status should contain(PetEnums.Status.Available) + } + } + } + + /* + it should "find pets by tag" in { + val request = api.findPetsByTags(List("tag1", "tag2")) + + invoker + .execute(request) + .map { apiResponse => + apiResponse.code should be(200) + + val pets = apiResponse.content + pets should not be empty + + forAll(pets) { pet => + val tagNames = pet.tags.toList.flatten.map(_.name).collect { case Some(name) => name } + tagNames should contain atLeastOneOf("tag1", "tag2") + } + } + } + */ +} +