Add API contract test for discriminator subclass IRI generation

This commit is contained in:
Mateusz 2026-06-12 14:14:03 +02:00
parent 509e354a0a
commit 6b7d0037fc
9 changed files with 236 additions and 0 deletions

View file

@ -0,0 +1,8 @@
api_platform:
mapping:
paths:
- '%kernel.project_dir%/tests/Api/Resource'
services:
Sylius\Tests\Api\Resource\SampleProductProvider:
tags: ['api_platform.state_provider']

View file

@ -0,0 +1,8 @@
api_platform:
mapping:
paths:
- '%kernel.project_dir%/tests/Api/Resource'
services:
Sylius\Tests\Api\Resource\SampleProductProvider:
tags: ['api_platform.state_provider']

View file

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Tests\Api\Admin;
use PHPUnit\Framework\Attributes\Test;
use Sylius\Tests\Api\JsonApiTestCase;
use Sylius\Tests\Api\Utils\AdminUserLoginTrait;
use Symfony\Component\HttpFoundation\Response;
final class SampleProductsTest extends JsonApiTestCase
{
use AdminUserLoginTrait;
#[Test]
public function it_generates_admin_iris_for_resource_subclass_instances(): void
{
$this->loadFixturesFromFile('authentication/api_administrator.yaml');
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
$this->client->request(
method: 'GET',
uri: '/api/v2/admin/sample-products',
server: $header,
);
$this->assertResponse(
$this->client->getResponse(),
'admin/sample_product/get_sample_products_response',
Response::HTTP_OK,
);
}
}

View file

@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Tests\Api\Resource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
#[ApiResource(operations: [
new GetCollection(
uriTemplate: '/admin/sample-products',
name: 'sylius_api_admin_sample_product_get_collection',
provider: SampleProductProvider::class,
),
new Get(
uriTemplate: '/admin/sample-products/{id}',
name: 'sylius_api_admin_sample_product_get',
provider: SampleProductProvider::class,
),
new GetCollection(
uriTemplate: '/shop/sample-products',
name: 'sylius_api_shop_sample_product_get_collection',
provider: SampleProductProvider::class,
),
new Get(
uriTemplate: '/shop/sample-products/{id}',
name: 'sylius_api_shop_sample_product_get',
provider: SampleProductProvider::class,
),
])]
class SampleProduct
{
public function __construct(
private int $id,
private string $name,
) {
}
public function getId(): int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
}

View file

@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Tests\Api\Resource;
use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
/** @implements ProviderInterface<SampleProduct> */
final readonly class SampleProductProvider implements ProviderInterface
{
public function provide(Operation $operation, array $uriVariables = [], array $context = []): array|object
{
if ($operation instanceof CollectionOperationInterface) {
return [new SpecialSampleProduct(1, 'Special Product')];
}
return new SpecialSampleProduct((int) ($uriVariables['id'] ?? 1), 'Special Product');
}
}

View file

@ -0,0 +1,22 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Tests\Api\Resource;
/**
* Simulates an entity subclass (e.g. a Doctrine discriminator map subclass)
* that is not an API resource itself, but extends a registered API resource.
*/
class SpecialSampleProduct extends SampleProduct
{
}

View file

@ -0,0 +1,14 @@
{
"@context": "\/api\/v2\/contexts\/SampleProduct",
"@id": "\/api\/v2\/admin\/sample-products",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "\/api\/v2\/admin\/sample-products\/1",
"@type": "SampleProduct",
"id": 1,
"name": "Special Product"
}
],
"hydra:totalItems": 1
}

View file

@ -0,0 +1,14 @@
{
"@context": "\/api\/v2\/contexts\/SampleProduct",
"@id": "\/api\/v2\/shop\/sample-products",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "\/api\/v2\/shop\/sample-products\/1",
"@type": "SampleProduct",
"id": 1,
"name": "Special Product"
}
],
"hydra:totalItems": 1
}

View file

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Tests\Api\Shop;
use PHPUnit\Framework\Attributes\Test;
use Sylius\Tests\Api\JsonApiTestCase;
use Symfony\Component\HttpFoundation\Response;
final class SampleProductsTest extends JsonApiTestCase
{
#[Test]
public function it_generates_shop_iris_for_resource_subclass_instances(): void
{
$this->client->request(
method: 'GET',
uri: '/api/v2/shop/sample-products',
server: self::CONTENT_TYPE_HEADER,
);
$this->assertResponse(
$this->client->getResponse(),
'shop/sample_product/get_sample_products_response',
Response::HTTP_OK,
);
}
}