core icon indicating copy to clipboard operation
core copied to clipboard

JsonSchema validation fail for non-readable link with `assertMatchesResourceItemJsonSchema`

Open TheoD02 opened this issue 1 year ago • 0 comments

API Platform version(s) affected: v3.3.7

Description
I'm currently testing API Platform as a POC for creating future REST APIs. Everything went fine until I tested an endpoint with ApiTestCase and used assertMatchesResourceItemJsonSchema().

How to reproduce

Resource:

class UserResource
{
    #[ApiProperty(identifier: true)]
    public int $id;

    public string $name;

    /**
     * @var ?CollectionInterface<int, ArticleResource> $articles
     */
    #[ApiProperty(readableLink: false)]
    public ?CollectionInterface $articles = null;
}

Input used:

class CreateUserInputDto
{
    #[Assert\NotBlank]
    #[Assert\Length(min: 3, max: 50)]
    public string $name;

    /**
     * @var array<CreateArticleInputDto> $articles
     */
    public array $articles = [];
}

class CreateArticleInputDto
{
    public string $title;

    public string $content;
}

Payload:

{
    "name": "Cool name!",
    "articles": [
        {
            "title": "Cool title!",
            "content": "Cool content!"
        }
    ]
}

Response:

{
    "@context": "/api/contexts/User",
    "@id": "/api/users/161",
    "@type": "User",
    "id": 161,
    "name": "Matilda",
    "articles": [
        "/api/articles/1048"
    ]
}

This endpoint works as expected, but the schema validation is incorrect. The JSON schema expects a list of article objects, not a list of IRIs for articles as defined by #[ApiProperty(readableLink: false)].

Failed asserting that Array &0 (
    '@context' => '/api/contexts/User'
    '@id' => '/api/users/1'
    '@type' => 'User'
    'id' => 1
    'name' => 'John Doe'
    'articles' => Array &1 (
        0 => '/api/articles/1'
    )
) matches the provided JSON Schema.
articles[0]: String value found, but an object is required

To pass the test correctly, if I define the ApiProperty attribute as below, everything works fine:

#[ApiProperty(readableLink: false, jsonSchemaContext: ['type' => 'array', 'items' => ['type' => 'string']])]

Is it necessary to manually add this to each field that exposes an IRI? Or can API Platform automatically handle this JSON schema context when the ApiProperty is defined as a non-readable link?

TheoD02 avatar Jul 09 '24 21:07 TheoD02