Skip to content

#5736 Create a failing scenario. #5747

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

Closed
wants to merge 19 commits into from

Conversation

Aerendir
Copy link
Contributor

Failing test scenario for #5736.

cc @soyuka

@Aerendir Aerendir force-pushed the issue-5736-aerendir branch from 53ce8f2 to ab4404a Compare August 12, 2023 14:30
@soyuka
Copy link
Member

soyuka commented Aug 21, 2023

@Aerendir can you check my patch at #5765 ?

@soyuka
Copy link
Member

soyuka commented Aug 22, 2023

I've spend quite some time and couldn't actually try this as the test case is incomplete

@Aerendir
Copy link
Contributor Author

@soyuka , I've just tested your PR #5765 directly in my app, but tests continue to fail.

I've used this:

"require": {
    ...
    "api-platform/core": "3.1.x-dev",
    ...

I'm going to create tests on version 3.1.12 that I'm sure works in my app: maybe I wrote broken tests...

@Aerendir
Copy link
Contributor Author

Aerendir commented Aug 22, 2023

@soyuka , I refined a bit the tests and fixed the tag...

EDITED

The first test, simply creating the Company works on both versions 3.1.12 and 3.1.14.

I'm going to fix the other tests...

@Aerendir Aerendir force-pushed the issue-5736-aerendir branch from 8e3a754 to 6ca0aa4 Compare August 22, 2023 16:47
@Aerendir Aerendir force-pushed the issue-5736-aerendir branch from 7fb3cd2 to 39eea31 Compare August 22, 2023 17:07
@Aerendir
Copy link
Contributor Author

Aerendir commented Aug 24, 2023

@soyuka , I've fixed a lot of issues with the test:

  • Added serialization groups
  • Configured the state processor
  • Added some setters and getters
  • Added some more fine grained scenarios

Unfortunately, the tests still don't work.

It is strange I cannot create a Team calling /issue5736_companies/1/issue5736_teams:

    Then the response status code should be 201                                        # Behat\MinkExtension\Context\MinkContext::assertResponseStatus()
      Current response status code is 400, but 201 expected.
      
      +--[ HTTP/1.1 400 | http://example.com/issue5736_companies/1/issue5736_teams | SymfonyDriver ]
      |
      |  {"@context":"\/contexts\/Error","@type":"hydra:Error","hydra:title":"An error occurred","hydra:description":"Unable to generate an IRI for the item of type \u0022ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Issue5736Aerendir\\Team\u0022","trace":[{"namespace":"","short_class":"","class":"","type":"","function":"","file":"\/Users\/Aerendir\/Documents\/JooServer\/Lab\/_Forks\/api-platform\/core\/src\/Symfony\/Routing\/IriConverter.php","line":181,"args":[]},{"namespace":"ApiPlatform\\Symfony\\Routing","short_class":"IriConverter","class":"ApiPlatform\\Symfony\\Routing\\IriConverter","type":"-\u003E","function":"generateSymfonyRoute","file":"\/Users\/Aerendir\/Documents\/JooServer\/Lab\/_Forks\/api-platform\/core\/src\/Symfony\/Routing\/IriConverter.php","line":158,"args":[["object","ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Issue5736Aerendir\\Team"],["integer",1],["object","ApiPlatform\\Metadata\\Get"],["array",[]],["object","ApiPlatform\\Metadata\\Get"]]},{"namespace":"A...
      |

This should work and should not be related to the PUT issue.

Any idea about the cause of the error? I've tried to debug, but, as I don't know well the inners of ApiPlatform, I don't know if what I see is what is expected.

I've tested on both 3.1.12 and 3.1.14.

To run the failing scenario (# 2):

XDEBUG_MODE=debug XDEBUG_SESSION=1 vendor/bin/behat --name "POST Company then POST Team" -vvv

Without fixing this, I cannot go forward to fix other tests :(

@soyuka
Copy link
Member

soyuka commented Aug 29, 2023

there was a getId missing... also why is your PUT using @id and a application/json content type instead of an application/ld+json one?

@Aerendir
Copy link
Contributor Author

Aerendir commented Aug 29, 2023

@soyuka , yes: I've just discovered the issue... But the error is hidden in other errors: I think that the message should be clearer: a thing that requires just 3 seconds to fix (adding a getId(), actually required me a lot of time of debugging to discover it)...

I really not know why I use application/json instead of application/ld+json: I didn't put any attention on this.

I was to ask you (forgiving me for the stupid question), which is the difference, but it seems here there is the answer: #2066

UPDATE

And I have just tested the scenarios on 3.1.14 and they work 🤦

@Aerendir
Copy link
Contributor Author

Aerendir commented Aug 29, 2023

@soyuka , finally I discovered the issue and identified it, isolated it and completed the reproducing scenarios! 🎉

I've just tested this PR on both versions:

  • 3.1.12: Works
  • 3.1.14: DOESN'T Work

Which is the problem

The problem is only with application/json.

When using application/json, in fact, the normalizer that is used is https://github.com/api-platform/core/blob/main/src/Serializer/ItemNormalizer.php; when using application/ld+json, instead, the normalizer used is https://github.com/api-platform/core/blob/main/src/JsonLd/Serializer/ItemNormalizer.php: they are two different normalizers!

Identified the file in which the problem happens, lets discuss about its causes.

The problem is the way the variable $uriVariables is populated (line 105).

private function getContextUriVariables(array $data, $operation, array $context): array
{
$uriVariables = $context['uri_variables'] ?? $data;
/** @var Link $uriVariable */
foreach ($operation->getUriVariables() as $uriVariable) {
if (isset($uriVariables[$uriVariable->getParameterName()])) {
continue;
}
foreach ($uriVariable->getIdentifiers() as $identifier) {
if (isset($data[$identifier])) {
$uriVariables[$uriVariable->getParameterName()] = $data[$identifier];
}
}
}
return $uriVariables;
}

Screenshot 2023-08-29 alle 18 31 53

Basically, $identifier is id: this comes from the configuration of the entity. For example:

new API\Link(fromClass: Team::class, toProperty: 'team', identifiers: ['id'])

Now, what basically happens is that $data is an entity in the form of an array.

This array has the key id that is the property of the entity (in this case, Employee::$id).

But this same property id is present also in the other entities.

More, each placeholder defined via the Link object refers to the ID of the corresponding entity, so the identifying property is always id.

But the values should be different.

In fact, I used always the first inserted entity (so Company had ID 1; Team had ID 1; Employee had ID 1): in these circumstances, the bug doesn't appear, as the IDs are all equals.

But, if we start to use Company::$id = 2 and Team::$id = 2, then the bug appears.

In fact, the script uses $identifier: this has 99% the value id (configured via Link object in the entity).

But this property exists also on the Employee (that is an array passed as $data to the method ItemNormalizer::getContextUriVariables().

So, what basically the method does, is get every time the same ID = 1 (the one of the Employee entity) and put it in $uriVariables.

Doing this, it breaks the creation of the IRIs. And this is the cause of the issue.

Now, in version 3.1.12 this didn't happened; now, in version 3.1.14, it happens.

WDYT?

PS

This also tells me that is possible that using application/ld+json fixes the problem, but anyway it remains when using application/json (that is, however, anyway supported).

I'm going to try to use application/ld+json in my app to see if this makes the tests pass.

@soyuka
Copy link
Member

soyuka commented Aug 30, 2023

@Aerendir yeah we're working on it with @romainallanot we came to the same conclusions and try to work on a fix

@Aerendir
Copy link
Contributor Author

@soyuka , I tried using application/ld+json and I confirm that works: no problems with named placeholders.

@Aerendir
Copy link
Contributor Author

Aerendir commented Sep 7, 2023

@soyuka , can I close this PR?

@soyuka soyuka closed this Sep 8, 2023
@soyuka
Copy link
Member

soyuka commented Sep 8, 2023

yes thanks @Aerendir for trying to find what was wrong I hope you'll get a nice API Platform experience from now on :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants