Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Slim] Upgrade API server integration tests to use Fake Petstore spec #354

Merged
merged 11 commits into from
Jun 23, 2018

Conversation

ybelenko
Copy link
Contributor

PR checklist

  • Read the contribution guidelines.
  • Ran the shell script under ./bin/ to update Petstore sample so that CIs can verify the change. (For instance, only need to run ./bin/{LANG}-petstore.sh and ./bin/security/{LANG}-petstore.sh if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in .\bin\windows\.
  • Filed the PR against the correct branch: master, 3.1.x, 4.0.x. Default: master.
  • Copied the technical committee to review the pull request if your PR is targeting a particular programming language.

Description of the PR

  1. Old Petstore spec swapped with Fake Petstore spec.
  2. postProcessOperations method overriden. Special value / properly escaped to avoid php syntax errors.
  3. Add own private static final LOGGER like in Code clean-up: Add own private static final LOGGER in each class #26
  4. toModelName copied from PHPClient codegen which is much more enhanced at that point.
  5. postProcessSupportingFileData method overriden. Sort action fixes static route shadowing Bump junit from 4.13 to 4.13.1 in /samples/client/petstore/java/retrofit2-play26 #7698, but it sorts operations only within tag. It means that if user place path appointmens/{id} in first api group(tag Appointmets for example) and appointments/me path in last group(tag MyResources), this sort function will produce broken stubs anyway.
  6. Main mustache template slightly improved to suppress most of notices and warnings.

I've checked all endpoints with petstore-with-fake-endpoints-models-for-testing.yaml from Swagger UI and most of responses are correct with only few exceptions. I will add failed endpoints description in few days.

cc @jfastnacht

Copy link
Member

@wing328 wing328 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good to me (but I've not yet tested it locally in my new machine)

@wing328
Copy link
Member

wing328 commented Jun 20, 2018

cc @jebentier @dkarlovi @mandrean @jfastnacht @ackintosh (PHP Technical Committee)

@ybelenko
Copy link
Contributor Author

@wing328 and others
I'm not sure about b765ad7 because it sorts operations within tag and doesn't solve route shadowing 100% times.

It means that if user place path appointmens/{id} in first api group(tag Appointmets for example) and appointments/me path in last group(tag MyResources), this sort function will produce broken stubs anyway.

I didn't check this scenario, but I'm sure that codegen will produce broken stubs. Maybe this commit is a half measure and needs to be removed.

@wing328
Copy link
Member

wing328 commented Jun 20, 2018

I didn't check this scenario, but I'm sure that codegen will produce broken stubs. Maybe this commit is a half measure and needs to be removed.

Thanks for reviewing the fix and I see your concern. We'll look into a better fix if someone reports an issue with a spec.

@ybelenko
Copy link
Contributor Author

ybelenko commented Jun 20, 2018

During testing with Swagger Editor.

I've added Access-Control-Allow-Origin manually for testing purposes.

$app->options('/{routes:.+}', function ($request, $response, $args) {
    return $response;
});

$app->add(function ($req, $res, $next) {
    $response = $next($req, $res);
    return $response
            ->withHeader('Access-Control-Allow-Origin', 'http://editor.swagger.io')
            ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization, api_key')
            ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});

Without that headers you can't test samples with Swagger Editor.

Test results:

Pet

  • POST: /pet
    • curl -X POST "http://petstore.swagger.io:80/v2/pet" -H "accept: application/xml" -H "Content-Type: application/json" -d "{ \"id\": 0, \"category\": { \"id\": 0, \"name\": \"string\" }, \"name\": \"doggie\", \"photoUrls\": [ \"string\" ], \"tags\": [ { \"id\": 0, \"name\": \"string\" } ], \"status\": \"available\"}"
    • 200: How about implementing addPet as a POST method ?
  • PUT: /pet
    • curl -X PUT "http://petstore.swagger.io:80/v2/pet" -H "accept: application/xml" -H "Content-Type: application/json" -d "{ \"id\": 0, \"category\": { \"id\": 0, \"name\": \"string\" }, \"name\": \"doggie\", \"photoUrls\": [ \"string\" ], \"tags\": [ { \"id\": 0, \"name\": \"string\" } ], \"status\": \"available\"}"
    • 200: How about implementing updatePet as a PUT method ?
  • GET: /pet/findByStatus
    • curl -X GET "http://petstore.swagger.io:80/v2/pet/findByStatus?status=available" -H "accept: application/xml"
    • 200: How about implementing findPetsByStatus as a GET method ?
  • GET: /pet/findByTags
    • curl -X GET "http://petstore.swagger.io:80/v2/pet/findByTags?tags=tag1,tag2" -H "accept: application/xml"
    • 200: How about implementing findPetsByTags as a GET method ?
  • GET: /pet/{petId}
    • curl -X GET "http://petstore.swagger.io:80/v2/pet/5" -H "accept: application/xml"
    • 200: How about implementing getPetById as a GET method ?
  • POST: /pet/{petId}
    • curl -X POST "http://petstore.swagger.io:80/v2/pet/5" -H "accept: application/xml" -H "Content-Type: application/x-www-form-urlencoded" -d "name=Max&status=available"
    • 200: How about implementing updatePetWithForm as a POST method ?
  • DELETE: /pet/{petId}
    • curl -X DELETE "http://petstore.swagger.io:80/v2/pet/5" -H "accept: application/xml" -H "api_key: secret_key"
    • 200: How about implementing deletePet as a DELETE method ?
  • POST: /pet/{petId}/uploadImage
    • curl -X POST "http://petstore.swagger.io:80/v2/pet/5/uploadImage" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "additionalMetadata=nice_photo" -F "file=@avatar_2f562b9de655_128.png;type=image/png"
    • 200: How about implementing uploadFile as a POST method ?

Store

  • GET: /store/inventory
    • curl -X GET "http://petstore.swagger.io:80/v2/store/inventory" -H "accept: application/json"
    • 200: How about implementing getInventory as a GET method ?
  • POST: /store/order
    • curl -X POST "http://petstore.swagger.io:80/v2/store/order" -H "accept: application/xml" -H "Content-Type: application/json" -d "{ \"id\": 0, \"petId\": 0, \"quantity\": 0, \"shipDate\": \"2018-06-20T09:13:48.481Z\", \"status\": \"placed\", \"complete\": false}"
    • 200: How about implementing placeOrder as a POST method ?
  • GET: /store/order/{order_id}
    • curl -X GET "http://petstore.swagger.io:80/v2/store/order/5" -H "accept: application/xml"
    • 200: How about implementing getOrderById as a GET method ?
  • DELETE: /store/order/{order_id}
    • curl -X DELETE "http://petstore.swagger.io:80/v2/store/order/5" -H "accept: application/xml"
    • 200: How about implementing deleteOrder as a DELETE method ?

User

  • POST: /user
    • curl -X POST "http://petstore.swagger.io:80/v2/user" -H "accept: application/xml" -H "Content-Type: application/json" -d "{ \"id\": 0, \"username\": \"string\", \"firstName\": \"string\", \"lastName\": \"string\", \"email\": \"string\", \"password\": \"string\", \"phone\": \"string\", \"userStatus\": 0}"
    • 200: How about implementing createUser as a POST method ?
  • POST: /user/createWithArray
    • curl -X POST "http://petstore.swagger.io:80/v2/user/createWithArray" -H "accept: application/xml" -H "Content-Type: application/json" -d "[ { \"id\": 0, \"username\": \"string\", \"firstName\": \"string\", \"lastName\": \"string\", \"email\": \"string\", \"password\": \"string\", \"phone\": \"string\", \"userStatus\": 0 }]"
    • 200: How about implementing createUsersWithArrayInput as a POST method ?
  • POST: /user/createWithList
    • curl -X POST "http://petstore.swagger.io:80/v2/user/createWithList" -H "accept: application/xml" -H "Content-Type: application/json" -d "[ { \"id\": 0, \"username\": \"string\", \"firstName\": \"string\", \"lastName\": \"string\", \"email\": \"string\", \"password\": \"string\", \"phone\": \"string\", \"userStatus\": 0 }]"
    • 200: How about implementing createUsersWithListInput as a POST method ?
  • GET: /user/login
    • curl -X GET "http://petstore.swagger.io:80/v2/user/login?username=bill_gates&password=qwerty" -H "accept: application/xml"
    • 200: How about implementing loginUser as a GET method ?
  • GET: /user/logout
    • curl -X GET "http://petstore.swagger.io:80/v2/user/logout" -H "accept: application/xml"
    • 200: How about implementing logoutUser as a GET method ?
  • GET: /user/{username}
    • curl -X GET "http://petstore.swagger.io:80/v2/user/bill_gates" -H "accept: application/xml"
    • 200: How about implementing getUserByName as a GET method ?
  • PUT: /user/{username}
    • curl -X PUT "http://petstore.swagger.io:80/v2/user/bill_gates" -H "accept: application/xml" -H "Content-Type: application/json" -d "{ \"id\": 0, \"username\": \"string\", \"firstName\": \"string\", \"lastName\": \"string\", \"email\": \"string\", \"password\": \"string\", \"phone\": \"string\", \"userStatus\": 0}"
    • 200: How about implementing updateUser as a PUT method ?
  • DELETE: /user/{username}
    • curl -X DELETE "http://petstore.swagger.io:80/v2/user/bill_gates" -H "accept: application/xml"
    • 200: How about implementing deleteUser as a DELETE method ?

fake_classname_tags 123#$%^

  • PATCH: /fake_classname_test
    • curl -X PATCH "http://petstore.swagger.io:80/v2/fake_classname_test" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"client\": \"string\"}"
    • 200: How about implementing testClassname as a PATCH method ?

fake

  • PATCH: /fake

    • curl -X PATCH "http://petstore.swagger.io:80/v2/fake" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"client\": \"string\"}"
    • 200: How about implementing testClientModel as a PATCH method ?
  • GET: /fake ✔️ (works correct with CURL)

    • curl -X GET "http://petstore.swagger.io:80/v2/fake?enum_query_string_array=%24&enum_query_string=_abc&enum_query_integer=-2&enum_query_double=-1.2" -H "accept: application/json" -H "enum_header_string_array: List [ ">" ]" -H "enum_header_string: (xyz)" -H "Content-Type: application/x-www-form-urlencoded" -d "enum_form_string_array=%3E&enum_form_string=(xyz)"
    • 200: How about implementing testEnumParameters as a GET method ?
  • POST: /fake ✔️ (Fixed in 9c251dd)

    • curl -X POST "http://petstore.swagger.io:80/v2/fake" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -d "number=55&double=68.35&pattern_without_delimiter=Pattern&byte=ccffee"
    • 200: How about implementing testEndpointParameters as a POST method
  • POST: /fake/outer/number ✔️ (Fixed in ff913d7)

    • curl -X POST "http://petstore.swagger.io:80/v2/fake/outer/number" -H "accept: application/json" -H "Content-Type: application/json" -d "0"
    • 200: How about implementing fakeOuterNumberSerialize as a POST method ?
  • POST: /fake/outer/string ✔️ (Fixed in ff913d7)

    • curl -X POST "http://petstore.swagger.io:80/v2/fake/outer/string" -H "accept: application/json" -H "Content-Type: application/json" -d "\"string\""
    • 200: How about implementing fakeOuterStringSerialize as a POST method ?
  • POST: /fake/outer/boolean ✔️ (Fixed in ff913d7)

    • curl -X POST "http://petstore.swagger.io:80/v2/fake/outer/boolean" -H "accept: application/json" -H "Content-Type: application/json" -d "true"
    • 200: How about implementing fakeOuterBooleanSerialize as a POST method ?
  • POST: /fake/outer/composite

    • curl -X POST "http://petstore.swagger.io:80/v2/fake/outer/composite" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"my_number\": 0, \"my_string\": \"string\", \"my_boolean\": true}"
    • 200: How about implementing fakeOuterCompositeSerialize as a POST method ?
  • GET: /fake/jsonFormData ✔️ (works correct with CURL)

    • curl -X GET "http://petstore.swagger.io:80/v2/fake/jsonFormData" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -d "param=foo&param2=bar"
    • 200: How about implementing testJsonFormData as a GET method ?
  • POST: /fake/inline-additionalProperties

    • curl -X POST "http://petstore.swagger.io:80/v2/fake/inline-additionalProperties" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"additionalProp1\": \"string\", \"additionalProp2\": \"string\", \"additionalProp3\": \"string\"}"
    • 200: How about implementing testInlineAdditionalProperties as a POST method ?
  • PUT: /fake/body-with-query-params

    • curl -X PUT "http://petstore.swagger.io:80/v2/fake/body-with-query-params?query=foo" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"id\": 0, \"username\": \"string\", \"firstName\": \"string\", \"lastName\": \"string\", \"email\": \"string\", \"password\": \"string\", \"phone\": \"string\", \"userStatus\": 0}"
    • 200: How about implementing testBodyWithQueryParams as a PUT method ?

$another-fake?

  • PATCH: /another-fake/dummy
    • curl -X PATCH "http://petstore.swagger.io:80/v2/another-fake/dummy" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"client\": \"string\"}"
    • 200: How about implementing testSpecialTags as a PATCH method ?

@ackintosh
Copy link
Contributor

@ybelenko Thanks for the enhancement!

POST: /fake/outer/number ❌
curl -X POST "http://petstore.swagger.io:80/v2/fake/outer/number" -H "accept: application/json" -H "Content-Type: application/json" -d "0"
Slim Application Error:
Type: RuntimeException
Message: Request body media type parser return value must be an array, an object, or null

It may caused by the invalid json request body -d "0" .
The endpoint works if use -d "{}" instead of -d "0". 💡

@ybelenko
Copy link
Contributor Author

@ackintosh
Who we should blame for this unexpected behaviour? Can we say that test spec file is broken(It's obvious that -d "0" is invalid JSON, but Swagger Editor use this value as default param without any warnings or errors)?

The same with:

TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.

Does this violate Swagger specification or any HTTP standards? Maybe we need to remove/change related endpoints, as soons as even Swagger Editor can't run it.

@wing328
Copy link
Member

wing328 commented Jun 21, 2018

Who we should blame for this unexpected behaviour?

@ybelenko Let's not blame anyone here as we've a blameless culture. If you really want someone to be "accountable", I'm don't mind taking the responsibility (and feel free to blame me offline via email or gitter)

Can we say that test spec file is broken(It's obvious that -d "0" is invalid JSON,

0 (number) is a valid JSON if I'm not mistaken (as confirmed with https://jsonlint.com/). According to https://www.json.org/

In JSON, they take on these forms:

One of these forms is

A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.

@ybelenko
Copy link
Contributor Author

@wing328
"Blame" not in a actual meaning. As soon as all errors are divided into client and server errors, then we need to clarify which implementation is responsible for any error. With no offence to anybody.

A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.

If so, then I need to check new versions of Slim Framework. Error occures before any route implementation, maybe I need to create issue, that Request class fails with correct JSON data.

Well, JSON is pretty straightforward. What about GET request with body? For me it's anti-pattern and wrong implementation. I'm really wondering why this kind of endpoints don't throw any errors or warning in Swagger Editor.

@wing328
Copy link
Member

wing328 commented Jun 21, 2018

Well, JSON is pretty straightforward. What about GET request with body? For me it's anti-pattern and wrong implementation. I'm really wondering why this kind of endpoints don't throw any errors or warning in Swagger Editor.

Looks like it's still "valid" to have a request body in a GET request:

Ref: https://stackoverflow.com/a/983458/677735

@ackintosh
Copy link
Contributor

0 (number) is a valid JSON

Oh..., sorry my misunderstand made you guys confused. 💦 @wing328 thanks for the reference! I learned from that.

@ybelenko As the errors listed in #354 (comment) is due to Slim Framework (or its components), the generated API server seems work fine for me. Do you have any issues about the API server?

@ybelenko
Copy link
Contributor Author

@wing328 @ackintosh
Finally, all endpoints works correct after last commit.

@ackintosh
Copy link
Contributor

c5f928a

Vendor folder with all dependencies removed to keep repo more clean.

👍 ✨

Copy link
Contributor

@ackintosh ackintosh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating the depencencies. LGTM!

@ackintosh ackintosh merged commit 36f4452 into OpenAPITools:master Jun 23, 2018
@ybelenko ybelenko deleted the slim_fake_petstore branch June 26, 2018 00:17
nilskuhn pushed a commit to nilskuhn/openapi-generator that referenced this pull request Apr 6, 2023
chore(deps): update dependency @types/node to v14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants