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
Fix symfony 5.2 api tests #5669
Fix symfony 5.2 api tests #5669
Conversation
25bb58c
to
7df0833
Compare
3ec5dd2
to
fbd924d
Compare
fbd924d
to
1afb574
Compare
@@ -104,7 +104,7 @@ public function testGet() | |||
{ | |||
$keyword = $this->testPost('keyword1', 'de', $this->category1->getId()); | |||
|
|||
$this->client->request( | |||
static::jsonRequest($this->client, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter should be in a separate line, like in all other places in this PR as well.
* @param mixed[] $parameters | ||
* @param mixed[] $server | ||
*/ | ||
protected static function jsonRequest(KernelBrowser $client, string $method, string $uri, array $parameters = [], array $server = [], bool $changeHistory = true): Crawler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not a huge fan of traits in PHP in general... But apart from that, why is that function static
? It would be a lot easier to use, because the $client
would not have to be passed (other traits also add member variables). And what is the changeHistory
parameter for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Traits for tests are fine and we use here lot of traits to inject our logic into SuluTestCase but also use them in third party test cases like PantherTestCase.
The method parameters are the same as for the normal request and have the same defaults so there is no bc break and easy to refractor this project by just replace $this->client->request(
with static::jsonRequest($this->client,
, think we should make the upgrade for our uses as easy as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that traits are kind of OK for tests, that's why I am not saying we should remove that trait. But I would still not make the function static
, because it would be even easier to change. It would basically be replacing $this->client->request
with $this->jsonRequest
(or should it be $this->requestJson
, to have the verb first in the method name?), and it would be easier to call, because there would be a parameter less to pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would make it static as we don't know where the method are used sometimes you have things in the setUpBeforeClass and you can only call static function where needed. Please keep in mind this need to be refractored in all our projects this method is not just for us in our tests and I just want to make there the upgrade as easy as possible by doing the replace. As we make it not static this will make it more complicated as it should be and the project query something in static methods can not longer use them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there should not be any requests in setUpBeforeClass
, or are there? Apart from that, this is a newly introduced function, so people have to change their code anyway, it won't work out of the box in any case. Therefore I think it is not worth paying the high price of a more complicated function call.
Actually I think I would not even have introduced the trait at all, but would have fixed the code in places where it is needed (not too many tests were failing). But I can see why you would want to have a trait, but I wouldn't have introduced it, since it just more code we have to maintain. But if we are doing it, I would make it easy to use in the future, and not making it complicated to keep some kind of BC, which is not really there anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there should not be any requests in setUpBeforeClass, or are there?
Sadly yes there are projects which create fixtures over apis for tests instead of creating them manually over the entity manager.
not too many tests were failing
But if we look all api tests which sends the json as request parameters instead as content are false test as we don't really test if the Api works really with json content thats why I think it correct to update all tests as I think all the tests are false implemented and not really testing there how the apis are used.
I would make it easy to use in the future, and not making it complicated to keep some kind of BC
Another method would be is override the createClient
method to write the $client
into a private static property and has private static::getClient
which symfony is using in there BrowserKitAssertionsTrait:
sadly we can currently not reuse the getClient of symfony as the method is private so we would need to implement the same behaviour by override the createClient
method call there a setter or implement something like symfony does which call the getClient but this did look for me hackier then just give the client to the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds more and more to me like we should fix that properly and use the client as Symfony intends it instead of creating a new abstraction that we have to maintain, is harder to understand and debug, and might lead to some problems in the future, especially if we also want to keep BC for that.
But if I am the only person thinking like that I am happy to be outvoted by @sulu/core-team.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have just seen that you have contributed a similar function in Symfony. Why not implementing it now in a way that it is compatible with that one, so that we can delete our code once we don't need it anymore? Even if it is more hacky (not sure if that is the case, since I don't know the implementation details) I would prefer that, because it is less likely to stay in our codebase than the current solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just had a deeper look, and I think all we have to do in order to make the new jsonRequest
function work you've introduced in your Symfony PR, is to decorate the test.client
service from symfony, because that seems to be what the createClient
method uses: https://github.com/symfony/symfony/blob/4.3/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php#L46
Then we can make use of that new function everywhere, and delete the code we copied from your Symfony PR (or maybe even the entire decorator) as soon as we only support Symfony versions containing this function. Or am I missing something?
if ('GET' !== $method) { | ||
// JSON_THROW_ON_ERROR requires at least php 7.3 | ||
$content = \json_encode($parameters, \defined('JSON_THROW_ON_ERROR') ? \JSON_THROW_ON_ERROR : 0); | ||
$parameters = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really get what's happening here... Is it logical to the user calling this function? Wouldn't it maybe be cleaner to separate $content
and $parameters
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GET
can not have content so and are added as query parameter in symfony when its a GET request. When its POST or request Methods its converted by symfony into request parameter. Here is the difference now that we convert it into the content instead of request parameter. I will add a comment here so its clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But what if we want to do a POST
request with query parameters and some content in the body? It's probably still possible by adding it as a string to the url like /admin?test=value
, but the $parameters
parameter would not work for that, even though I would have assumed that, since Symfony in general is working that way. For these reasons I would split the $parameters
and $content
, so that it works the same as in Symfony (you have also mentioned that the parameters are the same as in the Symfony request, so they should also work in the same way IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danrot also before when using POST query parameters has to be added as ?test=123
as symfony converts $parameters
into request parameters. Did update to use the same logic as symfony and linked the code. So it should be more clear now what happens here that instead of converting to request it is converted into json for the specific methods.
717b6a8
to
cbeb1d0
Compare
0c0cd7f
to
92a9819
Compare
…fony implementation in the future
7ac3de0
to
39ec403
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to check if the definition exists with as the test.client is only available in test env:
if ($container->hasDefinition('test.client')) {
$container->getDefinition('test.client')->setClass(SuluKernelBrowser::class);
}
@@ -233,7 +233,7 @@ public function testResponseHeader() | |||
$date = new DateTime(); | |||
$date->modify('+1 month'); | |||
|
|||
$this->client->request( | |||
$this->client->jsonRequest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like i forgot this. this should be a normal request as it is no json api:
$this->client->jsonRequest( | |
$this->client->request( |
Already realized the missing check 🙈 Also updated the request you've mentioned, that something I thought when I started working on this, but forgot to check afterwards 🙈 |
What's in this PR?
A new jsonRequest trait to be used instead of
client::request
.Why?
The json request need to be send as json body as symfony 5.2 browser kit does not longer allow none string values as parameters as they follow the http specification. So we need to do 5.2
Example Usage
Use search and replace to use the new method:
And: