diff --git a/composer.json b/composer.json index 56e32f271af..39f85cebc19 100644 --- a/composer.json +++ b/composer.json @@ -104,6 +104,7 @@ "api-platform/serializer": "self.version", "api-platform/state": "self.version", "api-platform/symfony": "self.version", + "api-platform/test": "self.version", "api-platform/validator": "self.version" }, "require": { @@ -117,7 +118,7 @@ "symfony/http-kernel": "^6.4.13 || ^7.0 || ^8.0", "symfony/property-access": "^6.4 || ^7.0 || ^8.0", "symfony/property-info": "^6.4 || ^7.1 || ^8.0", - "symfony/serializer": "^6.4 || ^7.0 || ^8.0", + "symfony/serializer": "^6.4.37 || ^7.4.9 || ^8.0.9", "symfony/translation-contracts": "^3.3", "symfony/type-info": "^7.4 || ^8.0", "symfony/validator": "^6.4.11 || ^7.1 || ^8.0", diff --git a/docs/guides/computed-field.php b/docs/guides/computed-field.php index 24b86bacee3..d6d4c230d5c 100644 --- a/docs/guides/computed-field.php +++ b/docs/guides/computed-field.php @@ -264,7 +264,7 @@ public function up(Schema $schema): void namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class ComputedFieldTest extends ApiTestCase { diff --git a/docs/guides/create-a-custom-doctrine-filter.php b/docs/guides/create-a-custom-doctrine-filter.php index 6ed8bf31bac..a6f03bddabc 100644 --- a/docs/guides/create-a-custom-doctrine-filter.php +++ b/docs/guides/create-a-custom-doctrine-filter.php @@ -120,7 +120,7 @@ public function up(Schema $schema): void namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; use App\Entity\Book; final class BookTest extends ApiTestCase diff --git a/docs/guides/custom-pagination.php b/docs/guides/custom-pagination.php index a83bac18724..7ed4a0181ae 100644 --- a/docs/guides/custom-pagination.php +++ b/docs/guides/custom-pagination.php @@ -147,7 +147,7 @@ public function load(ObjectManager $manager): void namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; use App\Entity\Book; final class BookTest extends ApiTestCase diff --git a/docs/guides/doctrine-entity-as-resource.php b/docs/guides/doctrine-entity-as-resource.php index b6d2a3b88e4..6cf1aa1b8f6 100644 --- a/docs/guides/doctrine-entity-as-resource.php +++ b/docs/guides/doctrine-entity-as-resource.php @@ -89,7 +89,7 @@ public function load(ObjectManager $manager): void namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class BookTest extends ApiTestCase { diff --git a/docs/guides/doctrine-search-filter.php b/docs/guides/doctrine-search-filter.php index bcf94c57336..e77084966d6 100644 --- a/docs/guides/doctrine-search-filter.php +++ b/docs/guides/doctrine-search-filter.php @@ -104,7 +104,7 @@ public function load(ObjectManager $manager): void namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; use App\Entity\Book; final class BookTest extends ApiTestCase diff --git a/docs/guides/error-provider.php b/docs/guides/error-provider.php index e417904008b..dba39c8f38a 100644 --- a/docs/guides/error-provider.php +++ b/docs/guides/error-provider.php @@ -84,7 +84,7 @@ function configure(ContainerConfigurator $configurator): void namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class BookTest extends ApiTestCase { diff --git a/docs/guides/error-resource.php b/docs/guides/error-resource.php index aee265e2831..866affaaf04 100644 --- a/docs/guides/error-resource.php +++ b/docs/guides/error-resource.php @@ -71,7 +71,7 @@ public static function provide(Operation $operation, array $uriVariables = [], a namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class BookTest extends ApiTestCase { diff --git a/docs/guides/extend-openapi-documentation.php b/docs/guides/extend-openapi-documentation.php index 0f7c0a62d68..3e2227c22e8 100644 --- a/docs/guides/extend-openapi-documentation.php +++ b/docs/guides/extend-openapi-documentation.php @@ -48,7 +48,7 @@ class Book namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class BookTest extends ApiTestCase { diff --git a/docs/guides/how-to.php b/docs/guides/how-to.php index 79aaa2a99c1..0d3aa856d34 100644 --- a/docs/guides/how-to.php +++ b/docs/guides/how-to.php @@ -124,7 +124,7 @@ function request(): Request namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; use App\Entity\Book; final class BookTest extends ApiTestCase diff --git a/docs/guides/http-cache-tags.php b/docs/guides/http-cache-tags.php index 9fdc9e543d3..0dda04efc18 100644 --- a/docs/guides/http-cache-tags.php +++ b/docs/guides/http-cache-tags.php @@ -96,7 +96,7 @@ function request(): Request namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class BookTest extends ApiTestCase { diff --git a/docs/guides/return-the-iri-of-your-resources-relations.php b/docs/guides/return-the-iri-of-your-resources-relations.php index 41fb3b779a9..8f27272ce71 100644 --- a/docs/guides/return-the-iri-of-your-resources-relations.php +++ b/docs/guides/return-the-iri-of-your-resources-relations.php @@ -173,7 +173,7 @@ function request(): Request } namespace App\Tests { - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; use App\ApiResource\Brand; final class BrandTest extends ApiTestCase diff --git a/docs/guides/test-your-api.php b/docs/guides/test-your-api.php index c0fea83ace5..fe0849ac859 100644 --- a/docs/guides/test-your-api.php +++ b/docs/guides/test-your-api.php @@ -9,10 +9,10 @@ namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; use App\ApiResource\Book; - // API Platform [testing utilities](/docs/core/testing/) provides an [ApiTestCase](/docs/reference/Symfony/Bundle/Test/ApiTestCase/) + // API Platform [testing utilities](/docs/core/testing/) provides an [ApiTestCase](/docs/reference/Test/ApiTestCase/) // that allows you to send an HTTP Request, and to perform assertions on the Response. final class BookTest extends ApiTestCase { @@ -20,7 +20,7 @@ final class BookTest extends ApiTestCase public function testBookDoesNotExists(): void { - // For starters we can get an [HTTP Client](/docs/reference/Symfony/Bundle/Test/Client/) with the `createClient` method. + // For starters we can get an [HTTP Client](/docs/reference/Test/Client/) with the `createClient` method. $client = static::createClient(); // Then, issue an HTTP request via this client, as we didn't load any data we'd expect this to send a 404 Not found. $client->request(method: 'GET', url: '/books/1'); diff --git a/docs/guides/validate-incoming-data.php b/docs/guides/validate-incoming-data.php index afefd71189a..d7a81dbc60e 100644 --- a/docs/guides/validate-incoming-data.php +++ b/docs/guides/validate-incoming-data.php @@ -121,7 +121,7 @@ function request(): Request namespace App\Tests { use ApiPlatform\Playground\Test\TestGuideTrait; - use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; + use ApiPlatform\Test\ApiTestCase; final class BookTest extends ApiTestCase { diff --git a/features/filter/filter_validation.feature b/features/filter/filter_validation.feature deleted file mode 100644 index 5119643e553..00000000000 --- a/features/filter/filter_validation.feature +++ /dev/null @@ -1,109 +0,0 @@ -Feature: Validate filters based upon filter description - - Background: - Given I add "Accept" header equal to "application/json" - - @createSchema - Scenario: Required filter should not throw an error if set - When I am on "/filter_validators?required=foo&required-allow-empty=&arrayRequired[foo]=" - Then the response status code should be 200 - - Scenario: Required filter that does not allow empty value should throw an error if empty - When I am on "/filter_validators?required=&required-allow-empty=&arrayRequired[foo]=" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'required: This value should not be blank.' - - Scenario: Required filter should throw an error if not set - When I am on "/filter_validators" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'required: This value should not be blank.\nrequired-allow-empty: This value should not be null.' - - Scenario: Required filter should not throw an error if set - When I am on "/array_filter_validators?arrayRequired[]=foo&indexedArrayRequired[foo]=foo" - Then the response status code should be 200 - - Scenario: Required filter should throw an error if not set - When I am on "/array_filter_validators" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'arrayRequired[]: This value should not be blank.\nindexedArrayRequired[foo]: This value should not be blank.' - - When I am on "/array_filter_validators?arrayRequired[foo]=foo" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'indexedArrayRequired[foo]: This value should not be blank.' - - When I am on "/array_filter_validators?arrayRequired[]=foo" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'indexedArrayRequired[foo]: This value should not be blank.' - - Scenario: Test filter bounds: maximum - When I am on "/filter_validators?required=foo&required-allow-empty&maximum=10" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&maximum=11" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'maximum: This value should be less than or equal to 10.' - - Scenario: Test filter bounds: exclusiveMaximum - When I am on "/filter_validators?required=foo&required-allow-empty&exclusiveMaximum=9" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&exclusiveMaximum=10" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'exclusiveMaximum: This value should be less than 10.' - - Scenario: Test filter bounds: minimum - When I am on "/filter_validators?required=foo&required-allow-empty&minimum=5" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&minimum=0" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'minimum: This value should be greater than or equal to 5.' - - Scenario: Test filter bounds: exclusiveMinimum - When I am on "/filter_validators?required=foo&required-allow-empty&exclusiveMinimum=6" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&exclusiveMinimum=5" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'exclusiveMinimum: This value should be greater than 5.' - - Scenario: Test filter bounds: max length - When I am on "/filter_validators?required=foo&required-allow-empty&max-length-3=123" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&max-length-3=1234" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'max-length-3: This value is too long. It should have 3 characters or less.' - - Scenario: Test filter bounds: min length - When I am on "/filter_validators?required=foo&required-allow-empty&min-length-3=123" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&min-length-3=12" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'min-length-3: This value is too short. It should have 3 characters or more.' - - Scenario: Test filter pattern - When I am on "/filter_validators?required=foo&required-allow-empty&pattern=pattern" - When I am on "/filter_validators?required=foo&required-allow-empty&pattern=nrettap" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&pattern=not-pattern" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'pattern: This value is not valid.' - - Scenario: Test filter enum - When I am on "/filter_validators?required=foo&required-allow-empty&enum=in-enum" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&enum=not-in-enum" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'enum: The value you selected is not a valid choice.' - - Scenario: Test filter multipleOf - When I am on "/filter_validators?required=foo&required-allow-empty&multiple-of=4" - Then the response status code should be 200 - - When I am on "/filter_validators?required=foo&required-allow-empty&multiple-of=3" - Then the response status code should be 422 - And the JSON node "detail" should be equal to 'multiple-of: This value should be a multiple of 2.' diff --git a/features/filter/property_filter.feature b/features/filter/property_filter.feature deleted file mode 100644 index 3b225793d3f..00000000000 --- a/features/filter/property_filter.feature +++ /dev/null @@ -1,28 +0,0 @@ -Feature: Set properties to include - In order to select specific properties from a resource - As a client software developer - I need to select attributes to retrieve - - @createSchema - Scenario: Test properties filter - Given there are 1 dummy objects with relatedDummy and its thirdLevel - When I send a "GET" request to "/dummies/1?properties[]=name&properties[]=alias&properties[]=relatedDummy&properties[]=name_converted" - Then the JSON node "name" should be equal to "Dummy #1" - And the JSON node "alias" should be equal to "Alias #0" - And the JSON node "relatedDummies" should not exist - And the JSON node "name_converted" should exist - - Scenario: Test relation embedding - When I send a "GET" request to "/dummies/1?properties[]=name&properties[]=alias&properties[relatedDummy][]=name" - Then the JSON node "name" should be equal to "Dummy #1" - And the JSON node "alias" should be equal to "Alias #0" - And the JSON node "relatedDummy.name" should be equal to "RelatedDummy #1" - And the JSON node "relatedDummies" should not exist - - Scenario: Test property filter on not resource relations - When I send a "GET" request to "/dummy-with-array-of-objects/1?properties[notResourceObject][]=foo&properties[arrayOfNotResourceObjects][]=bar" - Then the JSON node "notResourceObject.foo" should be equal to "foo" - And the JSON node "notResourceObject.bar" should not exist - And the JSON node "arrayOfNotResourceObjects[0].foo" should not exist - And the JSON node "arrayOfNotResourceObjects[0].bar" should be equal to "bar" - And the JSON node "id" should not exist diff --git a/features/http_cache/headers.feature b/features/http_cache/headers.feature deleted file mode 100644 index 7c000f79b05..00000000000 --- a/features/http_cache/headers.feature +++ /dev/null @@ -1,12 +0,0 @@ -Feature: Default values of HTTP cache headers - In order to make API responses cacheable - As an API software developer - I need to be able to set default cache headers values - - @createSchema - Scenario: Cache headers default value - When I send a "GET" request to "/relation_embedders" - Then the response status code should be 200 - And the header "Etag" should be equal to '"032297ac74d75a50"' - And the header "Cache-Control" should be equal to "max-age=60, public, s-maxage=3600" - And the header "Vary" should be equal to "Accept, Cookie, Accept-Language" diff --git a/features/http_cache/tag_collector_service.feature b/features/http_cache/tag_collector_service.feature deleted file mode 100644 index ed994aadb7e..00000000000 --- a/features/http_cache/tag_collector_service.feature +++ /dev/null @@ -1,268 +0,0 @@ -@sqlite -@customTagCollector -@disableForSymfonyLowest -Feature: Cache invalidation through HTTP Cache tags (custom TagCollector service) - In order to have a fast API - As an API software developer - I need to store API responses in a cache - - @createSchema - Scenario: Create a dummy resource - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation_embedders" with body: - """ - { - } - """ - Then the response status code should be 201 - And the header "Cache-Tags" should not exist - - Scenario: TagCollector can identify $object (IRI is overridden with custom logic) - When I send a "GET" request to "/relation_embedders/1" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/RE/1#anotherRelated,/RE/1#related,/RE/1" - - Scenario: Create some embedded resources - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation_embedders" with body: - """ - { - "anotherRelated": { - "name": "Related" - } - } - """ - Then the response status code should be 201 - And the header "Cache-Tags" should not exist - - Scenario: TagCollector can add cache tags for relations (JSON-LD format) - When I add "Accept" header equal to "application/ld+json" - And I send a "GET" request to "/relation_embedders/2" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/related_dummies/1#thirdLevel,/related_dummies/1,/RE/2#anotherRelated,/RE/2#related,/RE/2" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationEmbedder", - "@id": "/relation_embedders/2", - "@type": "RelationEmbedder", - "krondstadt": "Krondstadt", - "anotherRelated": { - "@id": "/related_dummies/1", - "@type": "https://schema.org/Product", - "symfony": "symfony", - "thirdLevel": null - }, - "related": null - } - """ - - Scenario: TagCollector can add cache tags for relations (HAL format) - When I add "Accept" header equal to "application/hal+json" - And I send a "GET" request to "/relation_embedders/2" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/RE/2,/related_dummies/1,/related_dummies/1#thirdLevel,/RE/2#anotherRelated,/RE/2#related" - And the JSON should be equal to: - """ - { - "_links": { - "self": { - "href": "/relation_embedders/2" - }, - "anotherRelated": { - "href": "/related_dummies/1" - } - }, - "_embedded": { - "anotherRelated": { - "_links": { - "self": { - "href": "/related_dummies/1" - } - }, - "symfony": "symfony" - } - }, - "krondstadt": "Krondstadt" - } - """ - - Scenario: TagCollector can add cache tags for relations (JSONAPI format) - When I add "Accept" header equal to "application/vnd.api+json" - And I send a "GET" request to "/relation_embedders/2" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/RE/2,/RE/2#anotherRelated,/RE/2#related" - And the JSON should be equal to: - """ - { - "data": { - "id": "/relation_embedders/2", - "type": "RelationEmbedder", - "attributes": { - "krondstadt": "Krondstadt" - }, - "relationships": { - "anotherRelated": { - "data": { - "type": "RelatedDummy", - "id": "/related_dummies/1" - } - }, - "related": { - "data": [] - } - } - } - } - """ - - Scenario: Create resource with extraProperties on ApiProperty - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/extra_properties_on_properties" with body: - """ - { - } - """ - Then the response status code should be 201 - And the header "Cache-Tags" should not exist - - Scenario: TagCollector can read propertyMetadata (tag is overridden with data from extraProperties) - When I send a "GET" request to "/extra_properties_on_properties/1" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/extra_properties_on_properties/1#overrideRelationTag,/extra_properties_on_properties/1" - - Scenario: Create two Relation2 - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation2s" with body: - """ - { - } - """ - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation2s" with body: - """ - { - } - """ - Then the response status code should be 201 - - Scenario: Create a Relation3 with many to many - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation3s" with body: - """ - { - "relation2s": ["/relation2s/1", "/relation2s/2"] - } - """ - Then the response status code should be 201 - - Scenario: Get a Relation3 (test collection of links; JSON-LD format) - When I add "Accept" header equal to "application/ld+json" - And I send a "GET" request to "/relation3s" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/relation3s/1#relation2s,/relation3s/1,/relation3s" - And the JSON should be equal to: - """ - { - "@context": "/contexts/Relation3", - "@id": "/relation3s", - "@type": "hydra:Collection", - "hydra:totalItems": 1, - "hydra:member": [ - { - "@id": "/relation3s/1", - "@type": "Relation3", - "id": 1, - "relation2s": [ - "/relation2s/1", - "/relation2s/2" - ] - } - ] - } - """ - - Scenario: Get a Relation3 (test collection of links; HAL format) - When I add "Accept" header equal to "application/hal+json" - And I send a "GET" request to "/relation3s" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/relation3s/1,/relation3s/1#relation2s,/relation3s" - And the JSON should be equal to: - """ - { - "_links": { - "self": { - "href": "/relation3s" - }, - "item": [ - { - "href": "/relation3s/1" - } - ] - }, - "totalItems": 1, - "itemsPerPage": 3, - "_embedded": { - "item": [ - { - "_links": { - "self": { - "href": "/relation3s/1" - }, - "relation2s": [ - { - "href": "/relation2s/1" - }, - { - "href": "/relation2s/2" - } - ] - }, - "id": 1 - } - ] - } - } - """ - - Scenario: Get a Relation3 (test collection of links; HAL format) - When I add "Accept" header equal to "application/vnd.api+json" - And I send a "GET" request to "/relation3s" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/relation3s/1,/relation3s/1#relation2s,/relation3s" - And the JSON should be equal to: - """ - { - "links": { - "self": "/relation3s" - }, - "meta": { - "totalItems": 1, - "itemsPerPage": 3, - "currentPage": 1 - }, - "data": [ - { - "id": "/relation3s/1", - "type": "Relation3", - "attributes": { - "_id": 1 - }, - "relationships": { - "relation2s": { - "data": [ - { - "type": "Relation2", - "id": "/relation2s/1" - }, - { - "type": "Relation2", - "id": "/relation2s/2" - } - ] - } - } - } - ] - } - """ diff --git a/features/http_cache/tags.feature b/features/http_cache/tags.feature deleted file mode 100644 index bcc5ed9370c..00000000000 --- a/features/http_cache/tags.feature +++ /dev/null @@ -1,142 +0,0 @@ -@sqlite -Feature: Cache invalidation through HTTP Cache tags - In order to have a fast API - As an API software developer - I need to store API responses in a cache - - @createSchema - Scenario: Create some embedded resources - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation_embedders" with body: - """ - { - "anotherRelated": { - "name": "Related", - "thirdLevel": {} - } - } - """ - Then the response status code should be 201 - And the header "Cache-Tags" should not exist - And "/relation_embedders,/related_dummies,/third_levels" IRIs should be purged - - Scenario: Tags must be set for items - When I send a "GET" request to "/relation_embedders/1" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/third_levels/1,/related_dummies/1,/relation_embedders/1" - - Scenario: Create some more resources - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation_embedders" with body: - """ - { - "anotherRelated": { - "name": "Another Related", - "thirdLevel": {} - } - } - """ - Then the response status code should be 201 - And the header "Cache-Tags" should not exist - - Scenario: Tags must be set for collections - When I send a "GET" request to "/relation_embedders" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/third_levels/1,/related_dummies/1,/relation_embedders/1,/third_levels/2,/related_dummies/2,/relation_embedders/2,/relation_embedders" - - Scenario: Purge item on update - When I add "Content-Type" header equal to "application/ld+json" - And I send a "PUT" request to "/relation_embedders/1" with body: - """ - { - "paris": "France" - } - """ - Then the response status code should be 200 - And the header "Cache-Tags" should not exist - And "/relation_embedders,/relation_embedders/1,/related_dummies/1" IRIs should be purged - - Scenario: Purge item and the related collection on update - When I add "Content-Type" header equal to "application/ld+json" - And I send a "DELETE" request to "/relation_embedders/1" - Then the response status code should be 204 - And the header "Cache-Tags" should not exist - And "/relation_embedders,/relation_embedders/1,/related_dummies/1" IRIs should be purged - - Scenario: Create two Relation2 - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation2s" with body: - """ - { - } - """ - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation2s" with body: - """ - { - } - """ - Then the response status code should be 201 - - Scenario: Embedded collection must be listed in cache tags - When I send a "GET" request to "/relation2s/1" - Then the header "Cache-Tags" should be equal to "/relation2s/1" - - Scenario: Create a Relation1 - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation1s" with body: - """ - { - "relation2": "/relation2s/1" - } - """ - Then the response status code should be 201 - And "/relation1s,/relation2s/1" IRIs should be purged - - Scenario: Update a Relation1 - When I add "Content-Type" header equal to "application/ld+json" - And I send a "PUT" request to "/relation1s/1" with body: - """ - { - "relation2": "/relation2s/2" - } - """ - Then the response status code should be 200 - And "/relation1s,/relation1s/1,/relation2s/2,/relation2s/1" IRIs should be purged - - Scenario: Create a Relation3 with many to many - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/relation3s" with body: - """ - { - "relation2s": ["/relation2s/1", "/relation2s/2"] - } - """ - Then the response status code should be 201 - And "/relation3s,/relation2s/1,/relation2s/2" IRIs should be purged - - Scenario: Get a Relation3 - When I add "Content-Type" header equal to "application/ld+json" - And I send a "GET" request to "/relation3s" - Then the response status code should be 200 - And the header "Cache-Tags" should be equal to "/relation2s/1,/relation2s/2,/relation3s/1,/relation3s" - - Scenario: Update a collection member only (legacy non-standard PUT) - When I add "Content-Type" header equal to "application/ld+json" - And I send a "PUT" request to "/relation3s/1" with body: - """ - { - "relation2s": ["/relation2s/2"] - } - """ - Then the response status code should be 200 - And the header "Cache-Tags" should not exist - And "/relation3s,/relation3s/1,/relation2s/2,/relation2s,/relation2s/1" IRIs should be purged - - Scenario: Delete the collection owner - When I add "Content-Type" header equal to "application/ld+json" - And I send a "DELETE" request to "/relation3s/1" - Then the response status code should be 204 - And the header "Cache-Tags" should not exist - And "/relation3s,/relation3s/1,/relation2s/2" IRIs should be purged - diff --git a/features/issues/5926.feature b/features/issues/5926.feature deleted file mode 100644 index 640d8a1bc6c..00000000000 --- a/features/issues/5926.feature +++ /dev/null @@ -1,36 +0,0 @@ -Feature: Issue 5926 - In order to reproduce the issue at https://github.com/api-platform/core/issues/5926 - As a client software developer - I need to be able to use every operation on a resource with non-resources embed objects - - @!mongodb - Scenario: Create and retrieve a WriteResource - When I add "Accept" header equal to "application/json" - And I send a "GET" request to "/test_issue5926s/1" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json; charset=utf-8" - - @!mongodb - Scenario: Create and retrieve a JSON:API WriteResource - When I add "Accept" header equal to "application/vnd.api+json" - And I send a "GET" request to "/test_issue5926s/1" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/vnd.api+json; charset=utf-8" - - @!mongodb - Scenario: Create and retrieve a LD+JSON WriteResource - When I add "Accept" header equal to "application/ld+json" - And I send a "GET" request to "/test_issue5926s/1" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - - @!mongodb - Scenario: Create and retrieve a HAL WriteResource - When I add "Accept" header equal to "application/hal+json" - And I send a "GET" request to "/test_issue5926s/1" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/hal+json; charset=utf-8" diff --git a/features/json/input_output.feature b/features/json/input_output.feature deleted file mode 100644 index 2a5a1143162..00000000000 --- a/features/json/input_output.feature +++ /dev/null @@ -1,40 +0,0 @@ -Feature: JSON DTO input and output - In order to use the API - As a client software developer - I need to be able to use DTOs on my resources as Input or Output objects. - - Background: - Given I add "Accept" header equal to "application/json" - And I add "Content-Type" header equal to "application/json" - - @createSchema - Scenario: Request a password reset - And I send a "POST" request to "/users_reset/password_reset_request" with body: - """ - { - "email": "user@example.com" - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json; charset=utf-8" - And the JSON should be equal to: - """ - { - "emailSentAt": "2019-07-05T15:44:00+00:00" - } - """ - - @createSchema - Scenario: Request a password reset for a non-existent user - And I send a "POST" request to "/users_reset/password_reset_request" with body: - """ - { - "email": "does-not-exist@example.com" - } - """ - Then the response status code should be 404 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/problem+json; charset=utf-8" - And the JSON node "detail" should be equal to "User does not exist." - diff --git a/features/json/relation.feature b/features/json/relation.feature deleted file mode 100644 index 3455d9d4123..00000000000 --- a/features/json/relation.feature +++ /dev/null @@ -1,229 +0,0 @@ -Feature: JSON relations support - In order to use a hypermedia API - As a client software developer - I need to be able to update relations between resources - - @createSchema - Scenario: Create a third level - When I add "Content-Type" header equal to "application/json" - And I send a "POST" request to "/third_levels" with body: - """ - { - "level": 3 - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/ThirdLevel", - "@id": "/third_levels/1", - "@type": "ThirdLevel", - "fourthLevel": null, - "badFourthLevel": null, - "id": 1, - "level": 3, - "test": true, - "relatedDummies": [] - } - """ - - Scenario: Create a new relation - When I add "Content-Type" header equal to "application/json" - And I send a "POST" request to "/relation_embedders" with body: - """ - { - "anotherRelated": { - "symfony": "laravel" - } - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationEmbedder", - "@id": "/relation_embedders/1", - "@type": "RelationEmbedder", - "krondstadt": "Krondstadt", - "anotherRelated": { - "@id": "/related_dummies/1", - "@type": "https://schema.org/Product", - "symfony": "laravel", - "thirdLevel": null - }, - "related": null - } - """ - - Scenario: Update the relation with a new one - When I add "Content-Type" header equal to "application/json" - And I send a "PUT" request to "/relation_embedders/1" with body: - """ - { - "anotherRelated": { - "symfony": "laravel2" - } - } - """ - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationEmbedder", - "@id": "/relation_embedders/1", - "@type": "RelationEmbedder", - "krondstadt": "Krondstadt", - "anotherRelated": { - "@id": "/related_dummies/2", - "@type": "https://schema.org/Product", - "symfony": "laravel2", - "thirdLevel": null - }, - "related": null - } - """ - - Scenario: Update an embedded relation using an IRI - When I add "Content-Type" header equal to "application/json" - And I send a "PUT" request to "/relation_embedders/1" with body: - """ - { - "anotherRelated": { - "id": "/related_dummies/1", - "symfony": "API Platform" - } - } - """ - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationEmbedder", - "@id": "/relation_embedders/1", - "@type": "RelationEmbedder", - "krondstadt": "Krondstadt", - "anotherRelated": { - "@id": "/related_dummies/1", - "@type": "https://schema.org/Product", - "symfony": "API Platform", - "thirdLevel": null - }, - "related": null - } - """ - - Scenario: Update an embedded relation - When I add "Content-Type" header equal to "application/json" - And I send a "PUT" request to "/relation_embedders/1" with body: - """ - { - "anotherRelated": { - "id": 1, - "symfony": "API Platform 2" - } - } - """ - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationEmbedder", - "@id": "/relation_embedders/1", - "@type": "RelationEmbedder", - "krondstadt": "Krondstadt", - "anotherRelated": { - "@id": "/related_dummies/1", - "@type": "https://schema.org/Product", - "symfony": "API Platform 2", - "thirdLevel": null - }, - "related": null - } - """ - - Scenario: Create a related dummy with a relation using plain identifiers - When I add "Content-Type" header equal to "application/json" - And I send a "POST" request to "/related_dummies" with body: - """ - { - "thirdLevel": "1" - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelatedDummy", - "@id": "/related_dummies/3", - "@type": "https://schema.org/Product", - "id": 3, - "name": null, - "symfony": "symfony", - "dummyDate": null, - "thirdLevel": { - "@id": "/third_levels/1", - "@type": "ThirdLevel", - "fourthLevel": null - }, - "relatedToDummyFriend": [], - "dummyBoolean": null, - "embeddedDummy": [], - "age": null - } - """ - - Scenario: Passing a (valid) plain identifier on a relation - When I add "Content-Type" header equal to "application/json" - And I send a "POST" request to "/dummies" with body: - """ - { - "relatedDummy": "1", - "relatedDummies": [ - "1" - ], - "name": "Dummy with plain relations" - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/Dummy", - "@id": "/dummies/1", - "@type": "Dummy", - "description": null, - "dummy": null, - "dummyBoolean": null, - "dummyDate": null, - "dummyFloat": null, - "dummyPrice": null, - "relatedDummy": "/related_dummies/1", - "relatedDummies": [ - "/related_dummies/1" - ], - "jsonData": [], - "arrayData": [], - "name_converted": null, - "relatedOwnedDummy": null, - "relatedOwningDummy": null, - "id": 1, - "name": "Dummy with plain relations", - "alias": null, - "foo": null - } - """ diff --git a/features/mercure/discover.feature b/features/mercure/discover.feature deleted file mode 100644 index fecc057506f..00000000000 --- a/features/mercure/discover.feature +++ /dev/null @@ -1,13 +0,0 @@ -Feature: Mercure discovery support - In order to let the client discovering the Mercure hub - As a client software developer - I need to retrieve the hub URL through a Link HTTP header - - @createSchema - Scenario: Checks that the Mercure Link is added - Given I send a "GET" request to "/dummy_mercures" - Then the header "Link" should contain '; rel="mercure"' - - Scenario: Checks that the Mercure Link is not added on endpoints where updates are not dispatched - Given I send a "GET" request to "/" - Then the header "Link" should not contain '; rel="mercure"' diff --git a/features/mercure/publish.feature b/features/mercure/publish.feature deleted file mode 100644 index ac0c27fa7ed..00000000000 --- a/features/mercure/publish.feature +++ /dev/null @@ -1,60 +0,0 @@ -Feature: Mercure publish support - In order to publish an Update to the Mercure hub - As a developer - I need to specify which topics I want to send the Update on - - @createSchema - # see https://github.com/api-platform/core/issues/5074 - Scenario: Checks that Mercure Updates are dispatched properly - Given I add "Accept" header equal to "application/ld+json" - And I add "Content-Type" header equal to "application/ld+json" - When I send a "POST" request to "/issue5074/mercure_with_topics" with body: - """ - { - "name": "Hello World!", - "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - Then 1 Mercure update should have been sent - And the Mercure update should have topics: - | http://example.com/issue5074/mercure_with_topics/1 | - And the Mercure update should have data: - """ - { - "@context": "/contexts/MercureWithTopics", - "@id": "/issue5074/mercure_with_topics/1", - "@type": "MercureWithTopics", - "id": 1, - "name": "Hello World!" - } - """ - - Scenario: Checks that Mercure Updates are dispatched following topics configured with expression language - Given I add "Accept" header equal to "application/ld+json" - And I add "Content-Type" header equal to "application/ld+json" - When I send a "POST" request to "/mercure_with_topics_and_get_operations" with body: - """ - { - "name": "Hello World!" - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - Then 1 Mercure update should have been sent - And the Mercure update should have topics: - | http://example.com/mercure_with_topics_and_get_operations/1 | - | http://example.com/custom_resource/mercure_with_topics_and_get_operations/1 | - And the Mercure update should have data: - """ - { - "@context": "/contexts/MercureWithTopicsAndGetOperation", - "@id": "/mercure_with_topics_and_get_operations/1", - "@type": "MercureWithTopicsAndGetOperation", - "id": 1, - "name": "Hello World!" - } - """ diff --git a/features/push_relations/push.feature b/features/push_relations/push.feature deleted file mode 100644 index fe4a7d1de75..00000000000 --- a/features/push_relations/push.feature +++ /dev/null @@ -1,17 +0,0 @@ -@sqlite -Feature: Push relations using HTTP/2 - In order to have a fast API - As an API software developer - I need to push relations using HTTP/2 - - @createSchema - Scenario: Push the relations of a collection of items - Given there are 2 dummy objects with relatedDummy - When I add "Content-Type" header equal to "application/ld+json" - And I send a "GET" request to "/dummies" - Then the header "Link" should be equal to '; rel="preload"; as="fetch",; rel="preload"; as="fetch",; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"' - - Scenario: Push the relations of an item - When I add "Content-Type" header equal to "application/ld+json" - And I send a "GET" request to "/dummies/1" - Then the header "Link" should be equal to '; rel="preload"; as="fetch",; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"' diff --git a/features/sub_resources/multiple_relation.feature b/features/sub_resources/multiple_relation.feature deleted file mode 100644 index c774257aa37..00000000000 --- a/features/sub_resources/multiple_relation.feature +++ /dev/null @@ -1,61 +0,0 @@ -Feature: JSON-LD multi relation - In order to use non-resource types - As a developer - I should be able to serialize types not mapped to an API resource. - - Background: - Given I add "Accept" header equal to "application/ld+json" - And I add "Content-Type" header equal to "application/ld+json" - - @createSchema - @!mongodb - Scenario: Get a multiple relation between to object - Given there is a relationMultiple object - When I send a "GET" request to "/dummy/1/relations/2" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationMultiple", - "@id": "/dummy/1/relations/2", - "@type": "RelationMultiple", - "id": 1, - "first": "/dummies/1", - "second": "/dummies/2" - } - """ - - @!mongodb - Scenario: Get all multiple relation of an object - Given there is a dummy object with many multiple relation - When I send a "GET" request to "/dummy/1/relations" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/RelationMultiple", - "@id": "/dummy/1/relations", - "@type": "hydra:Collection", - "hydra:member": [ - { - "@id": "/dummy/1/relations/2", - "@type": "RelationMultiple", - "id": 1, - "first": "/dummies/1", - "second": "/dummies/2" - }, - { - "@id": "/dummy/1/relations/3", - "@type": "RelationMultiple", - "id": 2, - "first": "/dummies/1", - "second": "/dummies/3" - } - ], - "hydra:totalItems": 2 - } - """ diff --git a/features/xml/deserialization.feature b/features/xml/deserialization.feature deleted file mode 100644 index ae2d2ef66ab..00000000000 --- a/features/xml/deserialization.feature +++ /dev/null @@ -1,92 +0,0 @@ -Feature: XML Deserialization - In order to use the API with XML - As a client software developer - I need to be able to deserialize XML data - - Background: - Given I add "Accept" header equal to "application/xml" - And I add "Content-Type" header equal to "application/xml" - - @createSchema - Scenario: Posting an XML resource with a string value - When I send a "POST" request to "/resource_with_strings" with body: - """ - - - string - - """ - Then the response status code should be 201 - And the response should be in XML - And the header "Content-Type" should be equal to "application/xml; charset=utf-8" - - Scenario Outline: Posting an XML resource with a boolean value - When I send a "POST" request to "/resource_with_booleans" with body: - """ - - - - - """ - Then the response status code should be 201 - And the response should be in XML - And the header "Content-Type" should be equal to "application/xml; charset=utf-8" - Examples: - | value | - | true | - | false | - | 1 | - | 0 | - - Scenario Outline: Posting an XML resource with an integer value - When I send a "POST" request to "/resource_with_integers" with body: - """ - - - - - """ - Then the response status code should be 201 - And the response should be in XML - And the header "Content-Type" should be equal to "application/xml; charset=utf-8" - Examples: - | value | - | 42 | - | -6 | - | 1 | - | 0 | - - @!mysql - Scenario Outline: Posting an XML resource with a float value - When I send a "POST" request to "/resource_with_floats" with body: - """ - - - - - """ - Then the response status code should be 201 - And the response should be in XML - And the header "Content-Type" should be equal to "application/xml; charset=utf-8" - Examples: - | value | - | 3.14 | - | NaN | - | INF | - | -INF | - - Scenario: Posting an XML resource with a collection with only one element - When I send a "POST" request to "/dummy_properties" with body: - """ - - - - - bar - - - - """ - Then the response status code should be 201 - And the response should be in XML - And the header "Content-Type" should be equal to "application/xml; charset=utf-8" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a221b595573..a5d96bdef5b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -13,7 +13,7 @@ parameters: objectManagerLoader: tests/Fixtures/app/object-manager.php bootstrapFiles: # We're aliasing classes for phpunit in this file, it needs to be added here see phpstan/#2194 - - src/Symfony/Bundle/Test/Constraint/ArraySubset.php + - src/Test/Constraint/ArraySubset.php - tests/Fixtures/app/AppKernel.php excludePaths: @@ -153,7 +153,7 @@ parameters: - src/Metadata/Tests - src/OpenApi/Tests - src/Serializer/Tests - - src/Symfony/Bundle/Test + - src/Test - src/Symfony/Tests - tests - @@ -175,7 +175,7 @@ parameters: - identifier: argument.templateType paths: - - src/Symfony/Bundle/Test + - src/Test - tests - src # TODO diff --git a/src/GraphQl/Type/FieldsBuilder.php b/src/GraphQl/Type/FieldsBuilder.php index 458f92bb248..4d674368723 100644 --- a/src/GraphQl/Type/FieldsBuilder.php +++ b/src/GraphQl/Type/FieldsBuilder.php @@ -512,20 +512,16 @@ private function getParameterArgs(Operation $operation, array $args = []): array $name = key($leafs); $filterLeafs = []; - if (($filterId = $parameter->getFilter()) && $this->filterLocator->has($filterId)) { - $filter = $this->filterLocator->get($filterId); - - if ($filter instanceof FilterInterface) { - $property = $parameter->getProperty() ?? $name; - $property = str_replace('.', $this->nestingSeparator, $property); - $description = $filter->getDescription($operation->getClass()); - - foreach ($description as $descKey => $descValue) { - $descKey = str_replace('.', $this->nestingSeparator, $descKey); - parse_str($descKey, $descValues); - if (isset($descValues[$property]) && \is_array($descValues[$property])) { - $filterLeafs = array_merge($filterLeafs, $descValues[$property]); - } + if ($filter = $this->resolveFilter($parameter->getFilter())) { + $property = $parameter->getProperty() ?? $name; + $property = str_replace('.', $this->nestingSeparator, $property); + $description = $filter->getDescription($operation->getClass()); + + foreach ($description as $descKey => $descValue) { + $descKey = str_replace('.', $this->nestingSeparator, $descKey); + parse_str($descKey, $descValues); + if (isset($descValues[$property]) && \is_array($descValues[$property])) { + $filterLeafs = array_merge($filterLeafs, $descValues[$property]); } } } @@ -612,12 +608,12 @@ private function getFilterArgs(array $args, ?string $resourceClass, string $root } foreach ($resourceOperation->getFilters() ?? [] as $filterId) { - if (!$this->filterLocator->has($filterId)) { + if (!($filter = $this->resolveFilter($filterId))) { continue; } $entityClass = $this->getStateOptionsClass($resourceOperation, $resourceOperation->getClass()); - foreach ($this->filterLocator->get($filterId)->getDescription($entityClass) as $key => $description) { + foreach ($filter->getDescription($entityClass) as $key => $description) { $filterType = \in_array($description['type'], TypeIdentifier::values(), true) ? Type::builtin($description['type']) : Type::object($description['type']); if (!($description['required'] ?? false)) { $filterType = Type::nullable($filterType); @@ -751,4 +747,24 @@ private function normalizePropertyName(string $property, string $resourceClass): return $this->nameConverter->normalize($property, $resourceClass); } + + /** + * Resolves a filter reference to a {@see FilterInterface} instance, supporting + * both a string service id (legacy/locator path) and an object form + * (`new QueryParameter(filter: new SortFilter())`). + */ + private function resolveFilter(mixed $filter): ?FilterInterface + { + if ($filter instanceof FilterInterface) { + return $filter; + } + + if (\is_string($filter) && $this->filterLocator->has($filter)) { + $resolved = $this->filterLocator->get($filter); + + return $resolved instanceof FilterInterface ? $resolved : null; + } + + return null; + } } diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 67c8ff4744b..3c14013ebc2 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -28,6 +28,8 @@ use ApiPlatform\Metadata\UrlGeneratorInterface; use ApiPlatform\Metadata\Util\ClassInfoTrait; use ApiPlatform\Metadata\Util\CloneTrait; +use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException as PropertyAccessInvalidArgumentException; +use Symfony\Component\PropertyAccess\Exception\InvalidTypeException; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; @@ -554,6 +556,8 @@ protected function setAttributeValue(object $object, string $attribute, mixed $v if (!isset($context['not_normalizable_value_exceptions'])) { throw $exception; } + } catch (PropertyAccessInvalidArgumentException $exception) { + throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to denormalize attribute "%s" value for class "%s": %s', $attribute, $object::class, $exception->getMessage()), $value, $exception instanceof InvalidTypeException ? [$exception->expectedType] : ['unknown'], $context['deserialization_path'] ?? null, false, $exception->getCode(), $exception); } } diff --git a/src/Serializer/composer.json b/src/Serializer/composer.json index 6bd700028c3..36b4517b39c 100644 --- a/src/Serializer/composer.json +++ b/src/Serializer/composer.json @@ -27,7 +27,7 @@ "api-platform/state": "^4.3", "symfony/property-access": "^6.4 || ^7.0 || ^8.0", "symfony/property-info": "^6.4 || ^7.1 || ^8.0", - "symfony/serializer": "^6.4 || ^7.0 || ^8.0", + "symfony/serializer": "^6.4.37 || ^7.4.9 || ^8.0.9", "symfony/validator": "^6.4.11 || ^7.0 || ^8.0" }, "require-dev": { diff --git a/src/Symfony/Bundle/ApiPlatformBundle.php b/src/Symfony/Bundle/ApiPlatformBundle.php index 9f449d6a854..b4749b48d7c 100644 --- a/src/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Symfony/Bundle/ApiPlatformBundle.php @@ -21,6 +21,7 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlResolverPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; +use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\JsonStreamerTransformerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MutatorPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\SerializerMappingLoaderPass; @@ -59,5 +60,7 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new AuthenticatorManagerPass()); $container->addCompilerPass(new SerializerMappingLoaderPass()); $container->addCompilerPass(new MutatorPass()); + // Must run after Symfony's TransformerPass so we can rely on the value_object_transformer tag being processed. + $container->addCompilerPass(new JsonStreamerTransformerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -10); } } diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/JsonStreamerTransformerPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/JsonStreamerTransformerPass.php new file mode 100644 index 00000000000..0a48ca6e9c1 --- /dev/null +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/JsonStreamerTransformerPass.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\JsonStreamer\Transformer\ValueObjectTransformerInterface; + +/** + * Builds a transformers locator merging "json_streamer.property_value_transformer", + * "json_streamer.value_transformer" (legacy) and "json_streamer.value_object_transformer" + * services, and assigns it to API Platform's custom JSON-LD stream reader/writer. + * + * FrameworkBundle's own TransformerPass only touches the standard json_streamer.stream_reader/writer + * services, not API Platform's JSON-LD-scoped ones; see https://github.com/symfony/symfony/pull/64190 + * for a proposed upstream fix that would make this pass obsolete. + * + * @internal + */ +final class JsonStreamerTransformerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!interface_exists(ValueObjectTransformerInterface::class)) { + return; + } + + if (!$container->hasDefinition('api_platform.jsonld.json_streamer.stream_reader') + && !$container->hasDefinition('api_platform.jsonld.json_streamer.stream_writer')) { + return; + } + + $map = []; + + foreach (['json_streamer.property_value_transformer', 'json_streamer.value_transformer'] as $tagName) { + foreach ($container->findTaggedServiceIds($tagName, true) as $id => $_) { + $map[$id] ??= new Reference($id); + } + } + + foreach ($container->findTaggedServiceIds('json_streamer.value_object_transformer', true) as $id => $_) { + $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); + if (!\is_string($class) || !method_exists($class, 'getValueObjectClassName')) { + continue; + } + + $map[$class::getValueObjectClassName()] = new Reference($id); + } + + $argument = new ServiceLocatorArgument($map); + + foreach (['api_platform.jsonld.json_streamer.stream_reader', 'api_platform.jsonld.json_streamer.stream_writer'] as $serviceId) { + if ($container->hasDefinition($serviceId)) { + $container->getDefinition($serviceId)->replaceArgument(0, $argument); + } + } + } +} diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php index 47ffb3dab3b..bd0c4bddb65 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Symfony\Bundle\Test\Client; +use ApiPlatform\Test\Client; use Symfony\Component\BrowserKit\AbstractBrowser; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Test/ApiTestAssertionsTrait.php similarity index 98% rename from src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php rename to src/Test/ApiTestAssertionsTrait.php index 7ac6daa9080..573bf35e113 100644 --- a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ b/src/Test/ApiTestAssertionsTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test; +namespace ApiPlatform\Test; use ApiPlatform\JsonSchema\BackwardCompatibleSchemaFactory; use ApiPlatform\JsonSchema\Schema; @@ -19,8 +19,8 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset; -use ApiPlatform\Symfony\Bundle\Test\Constraint\MatchesJsonSchema; +use ApiPlatform\Test\Constraint\ArraySubset; +use ApiPlatform\Test\Constraint\MatchesJsonSchema; use PHPUnit\Framework\Constraint\JsonMatches; use PHPUnit\Framework\ExpectationFailedException; use Symfony\Bundle\FrameworkBundle\Test\BrowserKitAssertionsTrait; diff --git a/src/Symfony/Bundle/Test/ApiTestCase.php b/src/Test/ApiTestCase.php similarity index 99% rename from src/Symfony/Bundle/Test/ApiTestCase.php rename to src/Test/ApiTestCase.php index 891b5f09ab9..5b3d80b7bc7 100644 --- a/src/Symfony/Bundle/Test/ApiTestCase.php +++ b/src/Test/ApiTestCase.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test; +namespace ApiPlatform\Test; use ApiPlatform\Metadata\IriConverterInterface; use PHPUnit\Framework\Attributes\After; diff --git a/src/Symfony/Bundle/Test/Client.php b/src/Test/Client.php similarity index 99% rename from src/Symfony/Bundle/Test/Client.php rename to src/Test/Client.php index 1936314ab54..90a2375263f 100644 --- a/src/Symfony/Bundle/Test/Client.php +++ b/src/Test/Client.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test; +namespace ApiPlatform\Test; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Component\BrowserKit\CookieJar; diff --git a/src/Symfony/Bundle/Test/ClientTrait.php b/src/Test/ClientTrait.php similarity index 92% rename from src/Symfony/Bundle/Test/ClientTrait.php rename to src/Test/ClientTrait.php index 147236420cf..3dd549057b5 100644 --- a/src/Symfony/Bundle/Test/ClientTrait.php +++ b/src/Test/ClientTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test; +namespace ApiPlatform\Test; trait ClientTrait { diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php b/src/Test/Constraint/ArraySubset.php similarity index 92% rename from src/Symfony/Bundle/Test/Constraint/ArraySubset.php rename to src/Test/Constraint/ArraySubset.php index 1078a7a4135..81564443d23 100644 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php +++ b/src/Test/Constraint/ArraySubset.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test\Constraint; +namespace ApiPlatform\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php b/src/Test/Constraint/ArraySubsetTrait.php similarity index 97% rename from src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php rename to src/Test/Constraint/ArraySubsetTrait.php index 12acdc6dc40..fffa1d85f83 100644 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php +++ b/src/Test/Constraint/ArraySubsetTrait.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test\Constraint; +namespace ApiPlatform\Test\Constraint; use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Exporter\Exporter; diff --git a/src/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php b/src/Test/Constraint/MatchesJsonSchema.php similarity index 98% rename from src/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php rename to src/Test/Constraint/MatchesJsonSchema.php index d16ba5e9539..90ac8ad43a2 100644 --- a/src/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php +++ b/src/Test/Constraint/MatchesJsonSchema.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test\Constraint; +namespace ApiPlatform\Test\Constraint; use JsonSchema\Validator; use PHPUnit\Framework\Constraint\Constraint; diff --git a/src/Test/README.md b/src/Test/README.md new file mode 100644 index 00000000000..1a513a53859 --- /dev/null +++ b/src/Test/README.md @@ -0,0 +1,14 @@ +# API Platform - Test + +Functional testing utilities for the [API Platform](https://api-platform.com) framework. + +Provides `ApiTestCase` and test assertions for building functional tests for API Platform applications. + +[Documentation](https://api-platform.com/docs/core/testing/) + +> [!CAUTION] +> +> This is a read-only sub split of `api-platform/core`, please +> [report issues](https://github.com/api-platform/core/issues) and +> [send Pull Requests](https://github.com/api-platform/core/pulls) +> in the [core API Platform repository](https://github.com/api-platform/core). diff --git a/src/Symfony/Bundle/Test/Response.php b/src/Test/Response.php similarity index 99% rename from src/Symfony/Bundle/Test/Response.php rename to src/Test/Response.php index 3ac943beedf..dfaae6e05e2 100644 --- a/src/Symfony/Bundle/Test/Response.php +++ b/src/Test/Response.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Symfony\Bundle\Test; +namespace ApiPlatform\Test; use Symfony\Component\BrowserKit\Response as BrowserKitResponse; use Symfony\Component\HttpClient\Exception\ClientException; diff --git a/src/Test/composer.json b/src/Test/composer.json new file mode 100644 index 00000000000..02e946521d1 --- /dev/null +++ b/src/Test/composer.json @@ -0,0 +1,68 @@ +{ + "name": "api-platform/test", + "description": "Testing utilities for API Platform", + "type": "library", + "keywords": [ + "REST", + "API", + "GraphQL", + "JSON-LD", + "Test", + "PHPUnit" + ], + "homepage": "https://api-platform.com", + "license": "MIT", + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr", + "homepage": "https://dunglas.fr" + }, + { + "name": "Antoine Bluchet", + "email": "soyuka@gmail.com", + "homepage": "https://soyuka.me" + } + ], + "require": { + "php": ">=8.2", + "api-platform/metadata": "^4.3", + "api-platform/json-schema": "^4.3", + "phpunit/phpunit": "^12.2", + "symfony/browser-kit": "^6.4 || ^7.0 || ^8.0", + "symfony/http-client": "^6.4 || ^7.0 || ^8.0", + "symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0" + }, + "suggest": { + "doctrine/orm": "To use findIriBy() with Doctrine ORM", + "doctrine/mongodb-odm": "To use findIriBy() with MongoDB", + "justinrainbow/json-schema": "To validate JSON schemas in assertions" + }, + "autoload": { + "psr-4": { + "ApiPlatform\\Test\\": "" + } + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true, + "allow-plugins": { + "composer/package-versions-deprecated": true, + "phpstan/extension-installer": true, + "php-http/discovery": true + } + }, + "extra": { + "branch-alias": { + "dev-main": "4.4.x-dev" + }, + "thanks": { + "name": "api-platform/api-platform", + "url": "https://github.com/api-platform/api-platform" + } + }, + "minimum-stability": "beta", + "prefer-stable": true +} \ No newline at end of file diff --git a/tests/Behat/JsonContext.php b/tests/Behat/JsonContext.php index 4450465fd08..cef891a41fa 100644 --- a/tests/Behat/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Behat; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use Behat\Gherkin\Node\PyStringNode; use Behat\Mink\Exception\ExpectationException; use Behatch\Context\JsonContext as BaseJsonContext; diff --git a/tests/Fixtures/TestBundle/ApiResource/Issue7966/SortFilterParameterDummy.php b/tests/Fixtures/TestBundle/ApiResource/Issue7966/SortFilterParameterDummy.php new file mode 100644 index 00000000000..423d89d951e --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/Issue7966/SortFilterParameterDummy.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7966; + +use ApiPlatform\Doctrine\Orm\Filter\SortFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\QueryParameter; + +#[ApiResource( + operations: [], + graphQlOperations: [ + new QueryCollection( + provider: [self::class, 'provide'], + paginationEnabled: false, + parameters: [ + 'order[:property]' => new QueryParameter(filter: new SortFilter()), + ], + ), + ], +)] +final class SortFilterParameterDummy +{ + public ?string $id = null; + public ?string $name = null; + + public static function provide(): array + { + return []; + } +} diff --git a/tests/Fixtures/TestBundle/ApiResource/NullOnNonNullableProperty/NullOnNonNullableResource.php b/tests/Fixtures/TestBundle/ApiResource/NullOnNonNullableProperty/NullOnNonNullableResource.php new file mode 100644 index 00000000000..fb6a59ee8fe --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/NullOnNonNullableProperty/NullOnNonNullableResource.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\NullOnNonNullableProperty; + +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Post; +use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + +#[Get( + shortName: 'NullOnNonNullableResource', + uriTemplate: '/null_on_non_nullable_resources/{id}', + provider: [self::class, 'provide'], +)] +#[Post( + shortName: 'NullOnNonNullableResource', + uriTemplate: '/null_on_non_nullable_resources', + processor: [self::class, 'process'], + denormalizationContext: [AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true], +)] +#[Post( + shortName: 'NullOnNonNullableResource', + uriTemplate: '/null_on_non_nullable_resources_collect', + processor: [self::class, 'process'], + denormalizationContext: [ + AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true, + DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true, + ], +)] +class NullOnNonNullableResource +{ + #[ApiProperty(identifier: true)] + public int $id = 1; + + public string $name; + + public static function provide(): self + { + $r = new self(); + $r->name = 'foo'; + + return $r; + } + + public static function process(self $data): self + { + return $data; + } +} diff --git a/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetChild.php b/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetChild.php new file mode 100644 index 00000000000..d50e257190d --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetChild.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PropertyFilter; + +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operation; + +#[ApiResource( + operations: [ + new Get( + uriTemplate: '/sparse_fieldset_children/{id}', + uriVariables: ['id'], + provider: [self::class, 'provide'], + ), + ], +)] +final class SparseFieldsetChild +{ + public function __construct( + #[ApiProperty(identifier: true)] + public int $id, + public string $name, + public ?string $description = null, + ) { + } + + public static function provide(Operation $operation, array $uriVariables = []): self + { + return new self((int) $uriVariables['id'], 'Child #'.$uriVariables['id'], 'A description'); + } +} diff --git a/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetParent.php b/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetParent.php new file mode 100644 index 00000000000..4eb2f7eae91 --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetParent.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PropertyFilter; + +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\Serializer\Filter\PropertyFilter; + +#[ApiResource( + operations: [ + new Get( + uriTemplate: '/sparse_fieldset_parents/{id}', + uriVariables: ['id'], + provider: [self::class, 'provide'], + ), + ], +)] +#[ApiFilter(PropertyFilter::class)] +final class SparseFieldsetParent +{ + public function __construct( + #[ApiProperty(identifier: true)] + public int $id, + public string $name, + public string $alias, + public string $nameConverted, + public ?SparseFieldsetChild $child = null, + ) { + } + + public static function provide(Operation $operation, array $uriVariables = []): self + { + $id = (int) $uriVariables['id']; + + return new self( + $id, + 'Parent #'.$id, + 'Alias #'.$id, + 'Converted '.$id, + new SparseFieldsetChild($id, 'Child #'.$id, 'A description'), + ); + } +} diff --git a/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetParentWithQueryParameter.php b/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetParentWithQueryParameter.php new file mode 100644 index 00000000000..405291bda02 --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/PropertyFilter/SparseFieldsetParentWithQueryParameter.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PropertyFilter; + +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\Metadata\QueryParameter; +use ApiPlatform\Serializer\Filter\PropertyFilter; + +#[Get( + uriTemplate: '/sparse_fieldset_parents_qp/{id}', + uriVariables: ['id'], + parameters: [ + 'properties' => new QueryParameter(filter: new PropertyFilter()), + ], + provider: [self::class, 'provide'], +)] +final class SparseFieldsetParentWithQueryParameter +{ + public function __construct( + #[ApiProperty(identifier: true)] + public int $id, + public string $name, + public string $alias, + public string $nameConverted, + public ?SparseFieldsetChild $child = null, + ) { + } + + public static function provide(Operation $operation, array $uriVariables = []): self + { + $id = (int) $uriVariables['id']; + + return new self( + $id, + 'Parent #'.$id, + 'Alias #'.$id, + 'Converted '.$id, + new SparseFieldsetChild($id, 'Child #'.$id, 'A description'), + ); + } +} diff --git a/tests/Functional/ArrayDtoTest.php b/tests/Functional/ArrayDtoTest.php index de7bce8e1a9..9ce5a88b57c 100644 --- a/tests/Functional/ArrayDtoTest.php +++ b/tests/Functional/ArrayDtoTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6211\ArrayPropertyDtoOperation; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Authorization/DenyTest.php b/tests/Functional/Authorization/DenyTest.php index 838de50670b..9c13c648de6 100644 --- a/tests/Functional/Authorization/DenyTest.php +++ b/tests/Functional/Authorization/DenyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Authorization; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6446\SecurityPostValidation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedLinkedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; diff --git a/tests/Functional/Authorization/LegacyDenyTest.php b/tests/Functional/Authorization/LegacyDenyTest.php index d93149724a5..8cd552d181d 100644 --- a/tests/Functional/Authorization/LegacyDenyTest.php +++ b/tests/Functional/Authorization/LegacyDenyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Authorization; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\LegacySecuredDummy; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/BackedEnumFilterTest.php b/tests/Functional/BackedEnumFilterTest.php index 224ded4dc49..944f361c484 100644 --- a/tests/Functional/BackedEnumFilterTest.php +++ b/tests/Functional/BackedEnumFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue7126\DummyForBackedEnumFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue7126\IntegerBackedEnum; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue7126\StringBackedEnum; diff --git a/tests/Functional/BackedEnumPropertyTest.php b/tests/Functional/BackedEnumPropertyTest.php index 335a5196287..09836cd5b00 100644 --- a/tests/Functional/BackedEnumPropertyTest.php +++ b/tests/Functional/BackedEnumPropertyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Person as PersonDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Person; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PersonToPet; diff --git a/tests/Functional/BackedEnumResourceTest.php b/tests/Functional/BackedEnumResourceTest.php index 94abdf74921..13df4afa55c 100644 --- a/tests/Functional/BackedEnumResourceTest.php +++ b/tests/Functional/BackedEnumResourceTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\BackedEnumIntegerResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\BackedEnumStringResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6264\Availability; diff --git a/tests/Functional/CursorPaginationEmptyCollectionTest.php b/tests/Functional/CursorPaginationEmptyCollectionTest.php index c1a45034165..1bafec5ecd5 100644 --- a/tests/Functional/CursorPaginationEmptyCollectionTest.php +++ b/tests/Functional/CursorPaginationEmptyCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CursorPaginatedDummy; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/DateTimeNormalizerPriorityTest.php b/tests/Functional/DateTimeNormalizerPriorityTest.php index b3ad733b6cc..9b9e6ee3905 100644 --- a/tests/Functional/DateTimeNormalizerPriorityTest.php +++ b/tests/Functional/DateTimeNormalizerPriorityTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\DateTimeNormalizationIssue; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/DefaultParametersTest.php b/tests/Functional/DefaultParametersTest.php index 6fdd6ad7f99..192464ea008 100644 --- a/tests/Functional/DefaultParametersTest.php +++ b/tests/Functional/DefaultParametersTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; /** * Tests that default parameters configured via api_platform.defaults.parameters diff --git a/tests/Functional/DeprecationHeaderTest.php b/tests/Functional/DeprecationHeaderTest.php index bdebfe481e7..dc7aee1b72c 100644 --- a/tests/Functional/DeprecationHeaderTest.php +++ b/tests/Functional/DeprecationHeaderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\DeprecationHeader; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Doctrine/ComputedFieldTest.php b/tests/Functional/Doctrine/ComputedFieldTest.php index 2433425b5d9..7a3aba61058 100644 --- a/tests/Functional/Doctrine/ComputedFieldTest.php +++ b/tests/Functional/Doctrine/ComputedFieldTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Cart; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CartProduct; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Doctrine/ContextSwitchTest.php b/tests/Functional/Doctrine/ContextSwitchTest.php index 3fc1564492f..52160b69e32 100644 --- a/tests/Functional/Doctrine/ContextSwitchTest.php +++ b/tests/Functional/Doctrine/ContextSwitchTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyContext; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyContextRelated; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Doctrine/EntityReadOnlyTest.php b/tests/Functional/Doctrine/EntityReadOnlyTest.php index 106da2f173b..28e84c591e2 100644 --- a/tests/Functional/Doctrine/EntityReadOnlyTest.php +++ b/tests/Functional/Doctrine/EntityReadOnlyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyReadOnly; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Doctrine/PartialPaginationMappedTest.php b/tests/Functional/Doctrine/PartialPaginationMappedTest.php index 0342c392649..7d44d62642d 100644 --- a/tests/Functional/Doctrine/PartialPaginationMappedTest.php +++ b/tests/Functional/Doctrine/PartialPaginationMappedTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PartialPaginationMappedResource; use ApiPlatform\Tests\Fixtures\TestBundle\Document\PartialPaginationMappedDocument; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Doctrine/PartialPaginationMongoDbTest.php b/tests/Functional/Doctrine/PartialPaginationMongoDbTest.php index 2b96b7691e9..36405751a49 100644 --- a/tests/Functional/Doctrine/PartialPaginationMongoDbTest.php +++ b/tests/Functional/Doctrine/PartialPaginationMongoDbTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\PartialPaginationMongo\PartialPaginationMongoDummy; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Doctrine/PartialPaginationTest.php b/tests/Functional/Doctrine/PartialPaginationTest.php index b0039078aec..805d00f2746 100644 --- a/tests/Functional/Doctrine/PartialPaginationTest.php +++ b/tests/Functional/Doctrine/PartialPaginationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\PartialPaginationDummy; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Doctrine/StateOptionTest.php b/tests/Functional/Doctrine/StateOptionTest.php index b77694aa74c..1a1c76dd5f5 100644 --- a/tests/Functional/Doctrine/StateOptionTest.php +++ b/tests/Functional/Doctrine/StateOptionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Doctrine; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6039\UserApi; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7689\Issue7689CategoryDto; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7689\Issue7689ProductDto; diff --git a/tests/Functional/DocumentationActionTest.php b/tests/Functional/DocumentationActionTest.php index 69d8ba90fde..c6205074847 100644 --- a/tests/Functional/DocumentationActionTest.php +++ b/tests/Functional/DocumentationActionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/tests/Functional/ErrorFormatTest.php b/tests/Functional/ErrorFormatTest.php index 3958cff0e9a..2e8b10aa834 100644 --- a/tests/Functional/ErrorFormatTest.php +++ b/tests/Functional/ErrorFormatTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7287\OperationWithDefaultFormat; use ApiPlatform\Tests\SetupClassResourcesTrait; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Functional/ErrorTest.php b/tests/Functional/ErrorTest.php index 92691c475a0..e7af775416d 100644 --- a/tests/Functional/ErrorTest.php +++ b/tests/Functional/ErrorTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Functional; use ApiPlatform\State\ApiResource\Error; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\DataUriFileUpload\FileUploadResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ErrorResourceWithGroups\Error as ErrorResourceWithGroupsError; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ErrorResourceWithGroups\ThrowsAnExceptionWithGroup; diff --git a/tests/Functional/Filter/FilterValidationTest.php b/tests/Functional/Filter/FilterValidationTest.php new file mode 100644 index 00000000000..93d455e827a --- /dev/null +++ b/tests/Functional/Filter/FilterValidationTest.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\Filter; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ArrayFilterValidator; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilterValidator; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; +use PHPUnit\Framework\Attributes\DataProvider; + +/** + * Validation built from legacy filter descriptions registered through the + * `filters` attribute on the resource. The QueryParameter equivalent is + * covered by {@see \ApiPlatform\Tests\Functional\Parameters\ValidationTest}. + */ +final class FilterValidationTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [FilterValidator::class, ArrayFilterValidator::class]; + } + + protected function setUp(): void + { + $this->recreateSchema($this->getResources()); + } + + public function testRequiredFilterValid(): void + { + self::createClient()->request('GET', '/filter_validators?required=foo&required-allow-empty=&arrayRequired[foo]=', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(200); + } + + public function testRequiredFilterBlank(): void + { + self::createClient()->request('GET', '/filter_validators?required=&required-allow-empty=&arrayRequired[foo]=', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains(['detail' => 'required: This value should not be blank.']); + } + + public function testRequiredFilterMissing(): void + { + self::createClient()->request('GET', '/filter_validators', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'detail' => "required: This value should not be blank.\nrequired-allow-empty: This value should not be null.", + ]); + } + + public function testArrayRequiredValid(): void + { + self::createClient()->request('GET', '/array_filter_validators?arrayRequired[]=foo&indexedArrayRequired[foo]=foo', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(200); + } + + public function testArrayRequiredMissing(): void + { + self::createClient()->request('GET', '/array_filter_validators', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'detail' => "arrayRequired[]: This value should not be blank.\nindexedArrayRequired[foo]: This value should not be blank.", + ]); + } + + public function testArrayRequiredOnlyOneKeyProvided(): void + { + self::createClient()->request('GET', '/array_filter_validators?arrayRequired[foo]=foo', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'detail' => 'indexedArrayRequired[foo]: This value should not be blank.', + ]); + + self::createClient()->request('GET', '/array_filter_validators?arrayRequired[]=foo', [ + 'headers' => ['Accept' => 'application/json'], + ]); + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'detail' => 'indexedArrayRequired[foo]: This value should not be blank.', + ]); + } + + public static function bounds(): iterable + { + yield 'maximum valid' => ['maximum=10', 200, null]; + yield 'maximum invalid' => ['maximum=11', 422, 'maximum: This value should be less than or equal to 10.']; + yield 'exclusiveMaximum valid' => ['exclusiveMaximum=9', 200, null]; + yield 'exclusiveMaximum invalid' => ['exclusiveMaximum=10', 422, 'exclusiveMaximum: This value should be less than 10.']; + yield 'minimum valid' => ['minimum=5', 200, null]; + yield 'minimum invalid' => ['minimum=0', 422, 'minimum: This value should be greater than or equal to 5.']; + yield 'exclusiveMinimum valid' => ['exclusiveMinimum=6', 200, null]; + yield 'exclusiveMinimum invalid' => ['exclusiveMinimum=5', 422, 'exclusiveMinimum: This value should be greater than 5.']; + yield 'max length valid' => ['max-length-3=123', 200, null]; + yield 'max length invalid' => ['max-length-3=1234', 422, 'max-length-3: This value is too long. It should have 3 characters or less.']; + yield 'min length valid' => ['min-length-3=123', 200, null]; + yield 'min length invalid' => ['min-length-3=12', 422, 'min-length-3: This value is too short. It should have 3 characters or more.']; + yield 'pattern valid' => ['pattern=nrettap', 200, null]; + yield 'pattern invalid' => ['pattern=not-pattern', 422, 'pattern: This value is not valid.']; + yield 'enum valid' => ['enum=in-enum', 200, null]; + yield 'enum invalid' => ['enum=not-in-enum', 422, 'enum: The value you selected is not a valid choice.']; + yield 'multipleOf valid' => ['multiple-of=4', 200, null]; + yield 'multipleOf invalid' => ['multiple-of=3', 422, 'multiple-of: This value should be a multiple of 2.']; + } + + #[DataProvider('bounds')] + public function testFilterBounds(string $extraQuery, int $expectedStatus, ?string $expectedDetail): void + { + $url = '/filter_validators?required=foo&required-allow-empty&'.$extraQuery; + + self::createClient()->request('GET', $url, [ + 'headers' => ['Accept' => 'application/json'], + ]); + + $this->assertResponseStatusCodeSame($expectedStatus); + if (null !== $expectedDetail) { + $this->assertJsonContains(['detail' => $expectedDetail]); + } + } +} diff --git a/tests/Functional/Filter/PropertyFilterTest.php b/tests/Functional/Filter/PropertyFilterTest.php new file mode 100644 index 00000000000..f12ac2d1449 --- /dev/null +++ b/tests/Functional/Filter/PropertyFilterTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\Filter; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PropertyFilter\SparseFieldsetChild; +use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PropertyFilter\SparseFieldsetParent; +use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\PropertyFilter\SparseFieldsetParentWithQueryParameter; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +/** + * Covers PropertyFilter sparse fieldset selection on resource relations. + * Non-resource selection is covered by {@see \ApiPlatform\Tests\Functional\JsonLd\NonResourceTest::testSparseFieldsetOnNonResourceObject}. + */ +final class PropertyFilterTest extends ApiTestCase +{ + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [ + SparseFieldsetParent::class, + SparseFieldsetParentWithQueryParameter::class, + SparseFieldsetChild::class, + ]; + } + + public function testApiFilterSelectsScalarProperties(): void + { + $response = self::createClient()->request( + 'GET', + '/sparse_fieldset_parents/1?properties[]=name&properties[]=alias&properties[]=nameConverted', + ['headers' => ['Accept' => 'application/ld+json']], + ); + + $body = $response->toArray(); + $this->assertSame('Parent #1', $body['name']); + $this->assertSame('Alias #1', $body['alias']); + // The name converter snake_cases this property at serialization time. + $this->assertSame('Converted 1', $body['name_converted']); + $this->assertArrayNotHasKey('child', $body); + } + + public function testApiFilterSelectsNestedRelationProperty(): void + { + $response = self::createClient()->request( + 'GET', + '/sparse_fieldset_parents/1?properties[]=name&properties[child][]=name', + ['headers' => ['Accept' => 'application/ld+json']], + ); + + $body = $response->toArray(); + $this->assertSame('Parent #1', $body['name']); + $this->assertSame('Child #1', $body['child']['name']); + $this->assertArrayNotHasKey('description', $body['child']); + $this->assertArrayNotHasKey('alias', $body); + } + + public function testQueryParameterSelectsScalarProperties(): void + { + $response = self::createClient()->request( + 'GET', + '/sparse_fieldset_parents_qp/1?properties[]=name&properties[]=alias', + ['headers' => ['Accept' => 'application/ld+json']], + ); + + $body = $response->toArray(); + $this->assertSame('Parent #1', $body['name']); + $this->assertSame('Alias #1', $body['alias']); + $this->assertArrayNotHasKey('child', $body); + $this->assertArrayNotHasKey('nameConverted', $body); + } + + public function testQueryParameterSelectsNestedRelationProperty(): void + { + $response = self::createClient()->request( + 'GET', + '/sparse_fieldset_parents_qp/1?properties[]=name&properties[child][]=name', + ['headers' => ['Accept' => 'application/ld+json']], + ); + + $body = $response->toArray(); + $this->assertSame('Parent #1', $body['name']); + $this->assertSame('Child #1', $body['child']['name']); + $this->assertArrayNotHasKey('description', $body['child']); + } +} diff --git a/tests/Functional/FormatTest.php b/tests/Functional/FormatTest.php index 80aab72cf95..d462573b174 100644 --- a/tests/Functional/FormatTest.php +++ b/tests/Functional/FormatTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6384\AcceptHtml; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/GenIdGlobalOptionTest.php b/tests/Functional/GenIdGlobalOptionTest.php index 729a1f9d309..f74dde595c7 100644 --- a/tests/Functional/GenIdGlobalOptionTest.php +++ b/tests/Functional/GenIdGlobalOptionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\AggregateRating; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\GenIdDefault; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\GenIdTrue; diff --git a/tests/Functional/GraphQl/Issue3975Test.php b/tests/Functional/GraphQl/Issue3975Test.php index ae4ad1e3928..c20b586753f 100644 --- a/tests/Functional/GraphQl/Issue3975Test.php +++ b/tests/Functional/GraphQl/Issue3975Test.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\GraphQl; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue3975\ActionSimulation; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/GraphQl/Issue7966Test.php b/tests/Functional/GraphQl/Issue7966Test.php new file mode 100644 index 00000000000..8b78adeebcd --- /dev/null +++ b/tests/Functional/GraphQl/Issue7966Test.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\GraphQl; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7966\SortFilterParameterDummy; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +/** + * Object-form filter (FilterInterface instance) combined with a bracketed parameter + * key crashed the GraphQL schema build because `filterLocator->has()` was called + * with the instance rather than a string service id. + * + * @see https://github.com/api-platform/core/issues/7966 + */ +final class Issue7966Test extends ApiTestCase +{ + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + /** + * @return class-string[] + */ + public static function getResources(): array + { + return [SortFilterParameterDummy::class]; + } + + public function testSchemaBuildsWithObjectFormFilterAndBracketedKey(): void + { + $response = self::createClient()->request('POST', '/graphql', ['json' => [ + 'query' => '{ __type(name: "SortFilterParameterDummy") { name } }', + ]]); + + $this->assertResponseIsSuccessful(); + $json = $response->toArray(false); + $this->assertArrayNotHasKey('errors', $json, json_encode($json['errors'] ?? null)); + $this->assertSame('SortFilterParameterDummy', $json['data']['__type']['name']); + } +} diff --git a/tests/Functional/GraphQl/SecurityTest.php b/tests/Functional/GraphQl/SecurityTest.php index 305927f1302..b49e19ce2ba 100644 --- a/tests/Functional/GraphQl/SecurityTest.php +++ b/tests/Functional/GraphQl/SecurityTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\GraphQl; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SecuredDummy as DocumentSecuredDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SecuredDummyCollection as DocumentSecuredDummyCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; diff --git a/tests/Functional/Hal/AbsoluteUrlTest.php b/tests/Functional/Hal/AbsoluteUrlTest.php index ee61a90757c..a4db9a00db7 100644 --- a/tests/Functional/Hal/AbsoluteUrlTest.php +++ b/tests/Functional/Hal/AbsoluteUrlTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\AbsoluteUrlChild; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\AbsoluteUrlParent; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/CollectionTest.php b/tests/Functional/Hal/CollectionTest.php index fa338eb8f08..51edfcf8201 100644 --- a/tests/Functional/Hal/CollectionTest.php +++ b/tests/Functional/Hal/CollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\CollectionPagedResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/HalTest.php b/tests/Functional/Hal/HalTest.php index bf1fbc77072..c87085be949 100644 --- a/tests/Functional/Hal/HalTest.php +++ b/tests/Functional/Hal/HalTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\HalRelatedResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\HalThirdLevel; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\RelationEmbedder; diff --git a/tests/Functional/Hal/InputOutputDtoTest.php b/tests/Functional/Hal/InputOutputDtoTest.php index 6ae2f29bb1f..cf7a4dfa5ce 100644 --- a/tests/Functional/Hal/InputOutputDtoTest.php +++ b/tests/Functional/Hal/InputOutputDtoTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\CustomOutputResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/ItemUriTemplateTest.php b/tests/Functional/Hal/ItemUriTemplateTest.php index 2196881211c..19135208bd2 100644 --- a/tests/Functional/Hal/ItemUriTemplateTest.php +++ b/tests/Functional/Hal/ItemUriTemplateTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\UriTemplateCar; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/MaxDepthTest.php b/tests/Functional/Hal/MaxDepthTest.php index 007aa270b34..62390935a60 100644 --- a/tests/Functional/Hal/MaxDepthTest.php +++ b/tests/Functional/Hal/MaxDepthTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\MaxDepthResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/NetworkPathTest.php b/tests/Functional/Hal/NetworkPathTest.php index d3dafe1bbd8..5755ad3567a 100644 --- a/tests/Functional/Hal/NetworkPathTest.php +++ b/tests/Functional/Hal/NetworkPathTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\NetworkPathParent; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\NetworkPathResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/NonResourceTest.php b/tests/Functional/Hal/NonResourceTest.php index 8292a16ec69..12c78c837ab 100644 --- a/tests/Functional/Hal/NonResourceTest.php +++ b/tests/Functional/Hal/NonResourceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\NonResourceContainer; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/ProblemTest.php b/tests/Functional/Hal/ProblemTest.php index 4c5e5136763..7ad877b57d2 100644 --- a/tests/Functional/Hal/ProblemTest.php +++ b/tests/Functional/Hal/ProblemTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\ProblemRelation; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Hal\ProblemResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Hal/PropertyCollectionIriOnlyTest.php b/tests/Functional/Hal/PropertyCollectionIriOnlyTest.php index dd92836af17..d38b09e6859 100644 --- a/tests/Functional/Hal/PropertyCollectionIriOnlyTest.php +++ b/tests/Functional/Hal/PropertyCollectionIriOnlyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnly; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnlyRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnlyRelationSecondLevel; diff --git a/tests/Functional/Hal/TableInheritanceTest.php b/tests/Functional/Hal/TableInheritanceTest.php index d5c1f89e86e..bec705415d3 100644 --- a/tests/Functional/Hal/TableInheritanceTest.php +++ b/tests/Functional/Hal/TableInheritanceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Hal; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceDifferentChild; diff --git a/tests/Functional/HalCircularReferenceTest.php b/tests/Functional/HalCircularReferenceTest.php index 2c95f50f988..8dc280a1fbb 100644 --- a/tests/Functional/HalCircularReferenceTest.php +++ b/tests/Functional/HalCircularReferenceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue4358\ResourceA; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue4358\ResourceB; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/HttpCache/CacheTagsTest.php b/tests/Functional/HttpCache/CacheTagsTest.php new file mode 100644 index 00000000000..3290b05de2c --- /dev/null +++ b/tests/Functional/HttpCache/CacheTagsTest.php @@ -0,0 +1,201 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\HttpCache; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\NullPurger; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Relation1; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Relation2; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Relation3; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelationEmbedder; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +final class CacheTagsTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [ + RelationEmbedder::class, + RelatedDummy::class, + ThirdLevel::class, + Relation1::class, + Relation2::class, + Relation3::class, + ]; + } + + protected function setUp(): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped('HTTP Cache tags only enabled on SQLite test suite'); + } + + $this->recreateSchema($this->getResources()); + $this->purger()->clear(); + } + + public function testFullCacheTagsLifecycle(): void + { + $client = self::createClient(); + + // Create an embedded relation; collection IRIs should be purged. + $client->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => [ + 'anotherRelated' => ['name' => 'Related', 'thirdLevel' => new \stdClass()], + ], + ]); + $this->assertResponseStatusCodeSame(201); + $this->assertResponseNotHasHeader('Cache-Tags'); + $this->assertSamePurgedIris([ + '/relation_embedders', + '/related_dummies', + '/third_levels', + ]); + + // Item GET exposes Cache-Tags. + $client->request('GET', '/relation_embedders/1'); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Cache-Tags', '/third_levels/1,/related_dummies/1,/relation_embedders/1'); + + // Create a second embedded relation. + $client->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['anotherRelated' => ['name' => 'Another Related', 'thirdLevel' => new \stdClass()]], + ]); + $this->assertResponseStatusCodeSame(201); + $this->assertResponseNotHasHeader('Cache-Tags'); + + // Collection GET aggregates per-item tags. + $client->request('GET', '/relation_embedders'); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame( + 'Cache-Tags', + '/third_levels/1,/related_dummies/1,/relation_embedders/1,/third_levels/2,/related_dummies/2,/relation_embedders/2,/relation_embedders', + ); + + // PUT purges item and related dummy. + $this->purger()->clear(); + $client->request('PUT', '/relation_embedders/1', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['paris' => 'France'], + ]); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseNotHasHeader('Cache-Tags'); + $this->assertSamePurgedIris(['/relation_embedders', '/relation_embedders/1', '/related_dummies/1']); + + // DELETE purges item and related dummy. + $this->purger()->clear(); + $client->request('DELETE', '/relation_embedders/1'); + $this->assertResponseStatusCodeSame(204); + $this->assertResponseNotHasHeader('Cache-Tags'); + $this->assertSamePurgedIris(['/relation_embedders', '/relation_embedders/1', '/related_dummies/1']); + } + + public function testManyToManyCacheTags(): void + { + $client = self::createClient(); + + // Two Relation2 instances. + $client->request('POST', '/relation2s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => new \stdClass(), + ]); + $client->request('POST', '/relation2s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => new \stdClass(), + ]); + $this->assertResponseStatusCodeSame(201); + + // Item GET on a Relation2 lists embedded collection tag. + $client->request('GET', '/relation2s/1'); + $this->assertResponseHeaderSame('Cache-Tags', '/relation2s/1'); + + // Many-to-one purges Relation2 sibling. + $this->purger()->clear(); + $client->request('POST', '/relation1s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['relation2' => '/relation2s/1'], + ]); + $this->assertResponseStatusCodeSame(201); + $this->assertSamePurgedIris(['/relation1s', '/relation2s/1']); + + // Replacing the relation purges old + new sides. + $this->purger()->clear(); + $client->request('PUT', '/relation1s/1', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['relation2' => '/relation2s/2'], + ]); + $this->assertResponseStatusCodeSame(200); + $this->assertSamePurgedIris(['/relation1s', '/relation1s/1', '/relation2s/2', '/relation2s/1']); + + // Many-to-many POST purges all referenced Relation2. + $this->purger()->clear(); + $client->request('POST', '/relation3s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['relation2s' => ['/relation2s/1', '/relation2s/2']], + ]); + $this->assertResponseStatusCodeSame(201); + $this->assertSamePurgedIris(['/relation3s', '/relation2s/1', '/relation2s/2']); + + // Collection GET aggregates tags including the collection IRI. + $client->request('GET', '/relation3s'); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Cache-Tags', '/relation2s/1,/relation2s/2,/relation3s/1,/relation3s'); + + // Updating a many-to-many removes a sibling and purges the old & new ones. + $this->purger()->clear(); + $client->request('PUT', '/relation3s/1', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['relation2s' => ['/relation2s/2']], + ]); + $this->assertResponseStatusCodeSame(200); + $this->assertSamePurgedIris(['/relation3s', '/relation3s/1', '/relation2s/2', '/relation2s', '/relation2s/1']); + + // Deleting the m2m owner purges the remaining sibling. + $this->purger()->clear(); + $client->request('DELETE', '/relation3s/1'); + $this->assertResponseStatusCodeSame(204); + $this->assertSamePurgedIris(['/relation3s', '/relation3s/1', '/relation2s/2']); + } + + private function assertSamePurgedIris(array $expected): void + { + $purged = $this->purger()->getIris(); + sort($expected); + sort($purged); + $this->assertSame($expected, $purged); + } + + private function purger(): NullPurger + { + $purger = static::getContainer()->get('test.api_platform.http_cache.purger'); + \assert($purger instanceof NullPurger); + + return $purger; + } + + private function isMongoDB(): bool + { + return 'mongodb' === static::getContainer()->getParameter('kernel.environment'); + } +} diff --git a/tests/Functional/HttpCache/HeadersTest.php b/tests/Functional/HttpCache/HeadersTest.php new file mode 100644 index 00000000000..3b5e81e3fc0 --- /dev/null +++ b/tests/Functional/HttpCache/HeadersTest.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\HttpCache; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelationEmbedder; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +final class HeadersTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [RelationEmbedder::class]; + } + + public function testDefaultCacheHeaders(): void + { + $this->recreateSchema([RelationEmbedder::class]); + + $response = self::createClient()->request('GET', '/relation_embedders'); + + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Etag', '"032297ac74d75a50"'); + $this->assertResponseHeaderSame('Cache-Control', 'max-age=60, public, s-maxage=3600'); + // Vary headers may come on multiple lines depending on the framework version. + $this->assertSame( + ['accept', 'cookie', 'accept-language'], + array_map('strtolower', $response->getHeaders()['vary'] ?? []), + ); + } +} diff --git a/tests/Functional/HttpCache/PushRelationsTest.php b/tests/Functional/HttpCache/PushRelationsTest.php new file mode 100644 index 00000000000..1a32195b9c3 --- /dev/null +++ b/tests/Functional/HttpCache/PushRelationsTest.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\HttpCache; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +final class PushRelationsTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [Dummy::class, RelatedDummy::class]; + } + + protected function setUp(): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped('HTTP/2 push only enabled on SQLite test suite'); + } + + $this->recreateSchema([Dummy::class, RelatedDummy::class]); + $this->loadDummies(2); + } + + public function testCollectionPushesRelatedIris(): void + { + self::createClient()->request('GET', '/dummies', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + ]); + + $this->assertResponseHeaderSame( + 'Link', + '; rel="preload"; as="fetch",; rel="preload"; as="fetch",; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"', + ); + } + + public function testItemPushesRelatedIri(): void + { + self::createClient()->request('GET', '/dummies/1', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + ]); + + $this->assertResponseHeaderSame( + 'Link', + '; rel="preload"; as="fetch",; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"', + ); + } + + private function loadDummies(int $count): void + { + $manager = static::getContainer()->get('doctrine')->getManager(); + + for ($i = 1; $i <= $count; ++$i) { + $related = new RelatedDummy(); + $related->setName('RelatedDummy #'.$i); + + $dummy = new Dummy(); + $dummy->setName('Dummy #'.$i); + $dummy->setAlias('Alias #'.($count - $i)); + $dummy->nameConverted = "Converted $i"; + $dummy->setRelatedDummy($related); + + $manager->persist($related); + $manager->persist($dummy); + } + + $manager->flush(); + } +} diff --git a/tests/Functional/HttpCache/TagCollectorTest.php b/tests/Functional/HttpCache/TagCollectorTest.php new file mode 100644 index 00000000000..71cb588595e --- /dev/null +++ b/tests/Functional/HttpCache/TagCollectorTest.php @@ -0,0 +1,211 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\HttpCache; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ExtraPropertiesOnProperty; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Relation2; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Relation3; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelationEmbedder; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; +use ApiPlatform\Tests\Fixtures\TestBundle\HttpCache\TagCollectorCustom; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +final class TagCollectorTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [ + RelationEmbedder::class, + RelatedDummy::class, + ThirdLevel::class, + ExtraPropertiesOnProperty::class, + Relation2::class, + Relation3::class, + ]; + } + + protected function setUp(): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped('Custom tag collector is only enabled on SQLite test suite'); + } + + // Force a fresh kernel so the custom collector replacement is in effect + // before any service that depends on it is instantiated. + static::ensureKernelShutdown(); + self::bootKernel(); + $container = static::getContainer(); + $container->set( + 'api_platform.http_cache.tag_collector', + new TagCollectorCustom($container->get('api_platform.iri_converter')), + ); + + $this->recreateSchema($this->getResources()); + } + + /** + * Returns a client that keeps the kernel alive between HTTP requests so the + * tag_collector override registered in setUp survives across calls. + */ + private function disableRebootClient(): \ApiPlatform\Test\Client + { + $client = self::createClient(); + $client->getKernelBrowser()->disableReboot(); + + return $client; + } + + public function testCustomTagsOnEmptyResource(): void + { + $this->disableRebootClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => new \stdClass(), + ]); + $this->assertResponseStatusCodeSame(201); + $this->assertResponseNotHasHeader('Cache-Tags'); + + $this->disableRebootClient()->request('GET', '/relation_embedders/1'); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Cache-Tags', '/RE/1#anotherRelated,/RE/1#related,/RE/1'); + } + + public function testCustomTagsForEmbeddedRelationJsonLd(): void + { + $this->disableRebootClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['anotherRelated' => ['name' => 'Related']], + ]); + $this->assertResponseStatusCodeSame(201); + + $this->disableRebootClient()->request('GET', '/relation_embedders/1', [ + 'headers' => ['Accept' => 'application/ld+json'], + ]); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame( + 'Cache-Tags', + '/related_dummies/1#thirdLevel,/related_dummies/1,/RE/1#anotherRelated,/RE/1#related,/RE/1', + ); + $this->assertJsonContains([ + '@context' => '/contexts/RelationEmbedder', + '@id' => '/relation_embedders/1', + '@type' => 'RelationEmbedder', + 'krondstadt' => 'Krondstadt', + 'anotherRelated' => [ + '@id' => '/related_dummies/1', + '@type' => 'https://schema.org/Product', + 'symfony' => 'symfony', + 'thirdLevel' => null, + ], + 'related' => null, + ]); + } + + public function testCustomTagsForEmbeddedRelationHal(): void + { + $this->disableRebootClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['anotherRelated' => ['name' => 'Related']], + ]); + + $this->disableRebootClient()->request('GET', '/relation_embedders/1', [ + 'headers' => ['Accept' => 'application/hal+json'], + ]); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame( + 'Cache-Tags', + '/RE/1,/related_dummies/1,/related_dummies/1#thirdLevel,/RE/1#anotherRelated,/RE/1#related', + ); + } + + public function testCustomTagsForEmbeddedRelationJsonApi(): void + { + $this->disableRebootClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['anotherRelated' => ['name' => 'Related']], + ]); + + $this->disableRebootClient()->request('GET', '/relation_embedders/1', [ + 'headers' => ['Accept' => 'application/vnd.api+json'], + ]); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame( + 'Cache-Tags', + '/RE/1,/RE/1#anotherRelated,/RE/1#related', + ); + } + + public function testCustomTagsFromApiPropertyExtraProperties(): void + { + $this->disableRebootClient()->request('POST', '/extra_properties_on_properties', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => new \stdClass(), + ]); + $this->assertResponseStatusCodeSame(201); + + $this->disableRebootClient()->request('GET', '/extra_properties_on_properties/1'); + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame( + 'Cache-Tags', + '/extra_properties_on_properties/1#overrideRelationTag,/extra_properties_on_properties/1', + ); + } + + /** + * Replaces the three "Get a Relation3 (test collection of links; ...)" behat + * scenarios. Each format asserts the same Cache-Tags set because the + * resource collection only contains link-only Relation2 references. + */ + public function testCustomTagsForManyToManyCollections(): void + { + $client = $this->disableRebootClient(); + $client->request('POST', '/relation2s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => new \stdClass(), + ]); + $client->request('POST', '/relation2s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => new \stdClass(), + ]); + $client->request('POST', '/relation3s', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['relation2s' => ['/relation2s/1', '/relation2s/2']], + ]); + $this->assertResponseStatusCodeSame(201); + + // Each format produces a different ordering of tags but the set must match. + $expected = ['/relation3s/1#relation2s', '/relation3s/1', '/relation3s']; + sort($expected); + + foreach (['application/ld+json', 'application/hal+json', 'application/vnd.api+json'] as $accept) { + $response = $client->request('GET', '/relation3s', ['headers' => ['Accept' => $accept]]); + $this->assertResponseStatusCodeSame(200); + $actual = explode(',', $response->getHeaders()['cache-tags'][0] ?? ''); + sort($actual); + $this->assertSame($expected, $actual, \sprintf('Cache-Tags mismatch for %s', $accept)); + } + } + + private function isMongoDB(): bool + { + return 'mongodb' === static::getContainer()->getParameter('kernel.environment'); + } +} diff --git a/tests/Functional/InputOutputNameConverterTest.php b/tests/Functional/InputOutputNameConverterTest.php index 07dbde490fd..67e85258ac2 100644 --- a/tests/Functional/InputOutputNameConverterTest.php +++ b/tests/Functional/InputOutputNameConverterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\DummyDtoNameConverted; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/IsGrantedTest.php b/tests/Functional/IsGrantedTest.php index 72c1cd10412..02997411fb9 100644 --- a/tests/Functional/IsGrantedTest.php +++ b/tests/Functional/IsGrantedTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\IsGrantedTestResource; use ApiPlatform\Tests\SetupClassResourcesTrait; use Symfony\Component\Security\Core\User\InMemoryUser; diff --git a/tests/Functional/Issue5926Test.php b/tests/Functional/Issue5926Test.php new file mode 100644 index 00000000000..e1beae16942 --- /dev/null +++ b/tests/Functional/Issue5926Test.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5926\TestIssue5926; +use ApiPlatform\Tests\SetupClassResourcesTrait; +use PHPUnit\Framework\Attributes\DataProvider; + +/** + * @see https://github.com/api-platform/core/issues/5926 + */ +final class Issue5926Test extends ApiTestCase +{ + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [TestIssue5926::class]; + } + + public static function formats(): iterable + { + yield ['application/json', 'application/json; charset=utf-8']; + yield ['application/vnd.api+json', 'application/vnd.api+json; charset=utf-8']; + yield ['application/ld+json', 'application/ld+json; charset=utf-8']; + yield ['application/hal+json', 'application/hal+json; charset=utf-8']; + } + + #[DataProvider('formats')] + public function testGetWriteResourceWithEmbeddedNonResourceCollection(string $accept, string $expectedContentType): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped(); + } + + self::createClient()->request('GET', '/test_issue5926s/1', [ + 'headers' => ['Accept' => $accept], + ]); + + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Content-Type', $expectedContentType); + } + + private function isMongoDB(): bool + { + return 'mongodb' === static::getContainer()->getParameter('kernel.environment'); + } +} diff --git a/tests/Functional/Json/InputOutputTest.php b/tests/Functional/Json/InputOutputTest.php new file mode 100644 index 00000000000..115ab628955 --- /dev/null +++ b/tests/Functional/Json/InputOutputTest.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\Json; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +final class InputOutputTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [User::class]; + } + + protected function setUp(): void + { + $this->recreateSchema([User::class]); + } + + public function testPasswordResetRequest(): void + { + self::createClient()->request('POST', '/users_reset/password_reset_request', [ + 'headers' => [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + 'json' => ['email' => 'user@example.com'], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/json; charset=utf-8'); + $this->assertJsonEquals(['emailSentAt' => '2019-07-05T15:44:00+00:00']); + } + + public function testPasswordResetRequestForUnknownUser(): void + { + self::createClient()->request('POST', '/users_reset/password_reset_request', [ + 'headers' => [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + 'json' => ['email' => 'does-not-exist@example.com'], + ]); + + $this->assertResponseStatusCodeSame(404); + $this->assertResponseHeaderSame('Content-Type', 'application/problem+json; charset=utf-8'); + $this->assertJsonContains(['detail' => 'User does not exist.']); + } +} diff --git a/tests/Functional/Json/RelationTest.php b/tests/Functional/Json/RelationTest.php new file mode 100644 index 00000000000..39095ee9251 --- /dev/null +++ b/tests/Functional/Json/RelationTest.php @@ -0,0 +1,219 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\Json; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelationEmbedder; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +/** + * Validates that JSON requests on resources accepting application/ld+json + * responses cover embedded creation, IRI relations and plain identifiers. + */ +final class RelationTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = true; + + public static function getResources(): array + { + return [ + ThirdLevel::class, + RelationEmbedder::class, + RelatedDummy::class, + Dummy::class, + ]; + } + + protected function setUp(): void + { + $this->recreateSchema($this->getResources()); + } + + public function testCreateThirdLevelReturnsLdJson(): void + { + self::createClient()->request('POST', '/third_levels', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['level' => 3], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/ThirdLevel', + '@id' => '/third_levels/1', + '@type' => 'ThirdLevel', + 'fourthLevel' => null, + 'badFourthLevel' => null, + 'id' => 1, + 'level' => 3, + 'test' => true, + 'relatedDummies' => [], + ]); + } + + public function testCreateEmbeddedRelation(): void + { + self::createClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['symfony' => 'laravel']], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/RelationEmbedder', + '@id' => '/relation_embedders/1', + '@type' => 'RelationEmbedder', + 'krondstadt' => 'Krondstadt', + 'anotherRelated' => [ + '@id' => '/related_dummies/1', + '@type' => 'https://schema.org/Product', + 'symfony' => 'laravel', + 'thirdLevel' => null, + ], + 'related' => null, + ]); + } + + public function testReplaceEmbeddedRelationCreatesNewRelated(): void + { + // Bootstrap a RelationEmbedder with a related dummy. + self::createClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['symfony' => 'laravel']], + ]); + + self::createClient()->request('PUT', '/relation_embedders/1', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['symfony' => 'laravel2']], + ]); + + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@id' => '/relation_embedders/1', + 'anotherRelated' => [ + '@id' => '/related_dummies/2', + '@type' => 'https://schema.org/Product', + 'symfony' => 'laravel2', + 'thirdLevel' => null, + ], + ]); + } + + public function testUpdateEmbeddedRelationUsingIri(): void + { + self::createClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['symfony' => 'laravel']], + ]); + + self::createClient()->request('PUT', '/relation_embedders/1', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['id' => '/related_dummies/1', 'symfony' => 'API Platform']], + ]); + + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + '@id' => '/relation_embedders/1', + 'anotherRelated' => [ + '@id' => '/related_dummies/1', + '@type' => 'https://schema.org/Product', + 'symfony' => 'API Platform', + 'thirdLevel' => null, + ], + ]); + } + + public function testUpdateEmbeddedRelationUsingPlainIdentifier(): void + { + self::createClient()->request('POST', '/relation_embedders', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['symfony' => 'laravel']], + ]); + + self::createClient()->request('PUT', '/relation_embedders/1', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['anotherRelated' => ['id' => 1, 'symfony' => 'API Platform 2']], + ]); + + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + '@id' => '/relation_embedders/1', + 'anotherRelated' => [ + '@id' => '/related_dummies/1', + 'symfony' => 'API Platform 2', + ], + ]); + } + + public function testCreateRelatedDummyWithPlainIdentifierForRelation(): void + { + self::createClient()->request('POST', '/third_levels', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['level' => 3], + ]); + + self::createClient()->request('POST', '/related_dummies', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => ['thirdLevel' => '1'], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains([ + '@context' => '/contexts/RelatedDummy', + '@id' => '/related_dummies/1', + '@type' => 'https://schema.org/Product', + 'thirdLevel' => [ + '@id' => '/third_levels/1', + '@type' => 'ThirdLevel', + 'fourthLevel' => null, + ], + ]); + } + + public function testCreateDummyWithPlainIdentifiersForRelations(): void + { + self::createClient()->request('POST', '/related_dummies', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => new \stdClass(), + ]); + + self::createClient()->request('POST', '/dummies', [ + 'headers' => ['Content-Type' => 'application/json'], + 'json' => [ + 'relatedDummy' => '1', + 'relatedDummies' => ['1'], + 'name' => 'Dummy with plain relations', + ], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains([ + '@context' => '/contexts/Dummy', + '@id' => '/dummies/1', + '@type' => 'Dummy', + 'relatedDummy' => '/related_dummies/1', + 'relatedDummies' => ['/related_dummies/1'], + 'name' => 'Dummy with plain relations', + ]); + } +} diff --git a/tests/Functional/JsonApi/AbsoluteUrlTest.php b/tests/Functional/JsonApi/AbsoluteUrlTest.php index 1566f03534c..dccad98d613 100644 --- a/tests/Functional/JsonApi/AbsoluteUrlTest.php +++ b/tests/Functional/JsonApi/AbsoluteUrlTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\AbsoluteUrlDummy; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\AbsoluteUrlRelationDummy; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/CollectionAttributesTest.php b/tests/Functional/JsonApi/CollectionAttributesTest.php index d19b84fa882..7a47c4efde4 100644 --- a/tests/Functional/JsonApi/CollectionAttributesTest.php +++ b/tests/Functional/JsonApi/CollectionAttributesTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\CircularReference; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/CollectionUriTemplateTest.php b/tests/Functional/JsonApi/CollectionUriTemplateTest.php index 8541a7de3a7..40a1cb00c2a 100644 --- a/tests/Functional/JsonApi/CollectionUriTemplateTest.php +++ b/tests/Functional/JsonApi/CollectionUriTemplateTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnly; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnlyRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnlyRelationSecondLevel; diff --git a/tests/Functional/JsonApi/CrudTest.php b/tests/Functional/JsonApi/CrudTest.php index fb759b9b4af..33069cc9b77 100644 --- a/tests/Functional/JsonApi/CrudTest.php +++ b/tests/Functional/JsonApi/CrudTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelationEmbedder; diff --git a/tests/Functional/JsonApi/EntrypointTest.php b/tests/Functional/JsonApi/EntrypointTest.php index ddc220247a5..d5b1419ee4d 100644 --- a/tests/Functional/JsonApi/EntrypointTest.php +++ b/tests/Functional/JsonApi/EntrypointTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\EntrypointDummy; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/ErrorTest.php b/tests/Functional/JsonApi/ErrorTest.php index 96a813c1d0b..21873394670 100644 --- a/tests/Functional/JsonApi/ErrorTest.php +++ b/tests/Functional/JsonApi/ErrorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\ErrorProblem; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiErrorTestResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/FilteringTest.php b/tests/Functional/JsonApi/FilteringTest.php index b44cb080998..a63c57be210 100644 --- a/tests/Functional/JsonApi/FilteringTest.php +++ b/tests/Functional/JsonApi/FilteringTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\FilteringDummy; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\FilteringProperty; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/IdentifierModeTest.php b/tests/Functional/JsonApi/IdentifierModeTest.php index 2f34c41ea5a..42abdc89fa4 100644 --- a/tests/Functional/JsonApi/IdentifierModeTest.php +++ b/tests/Functional/JsonApi/IdentifierModeTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiDummy; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiNotExposedRelation; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiRelatedDummy; diff --git a/tests/Functional/JsonApi/InputDtoTest.php b/tests/Functional/JsonApi/InputDtoTest.php index b42bab554ff..1868e90acd5 100644 --- a/tests/Functional/JsonApi/InputDtoTest.php +++ b/tests/Functional/JsonApi/InputDtoTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiInputResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiRequiredFieldsResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/InputOutputTest.php b/tests/Functional/JsonApi/InputOutputTest.php index 7cb8c5aa4bb..5ee63ca24ca 100644 --- a/tests/Functional/JsonApi/InputOutputTest.php +++ b/tests/Functional/JsonApi/InputOutputTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\CustomOutputResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/IriModeTest.php b/tests/Functional/JsonApi/IriModeTest.php index 429748ad16d..148229759d5 100644 --- a/tests/Functional/JsonApi/IriModeTest.php +++ b/tests/Functional/JsonApi/IriModeTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApiDummy; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/ItemUriTemplateTest.php b/tests/Functional/JsonApi/ItemUriTemplateTest.php index d80ed9965b7..0bb34908271 100644 --- a/tests/Functional/JsonApi/ItemUriTemplateTest.php +++ b/tests/Functional/JsonApi/ItemUriTemplateTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\UriTemplateCar; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/NetworkPathTest.php b/tests/Functional/JsonApi/NetworkPathTest.php index d8b35fed8cb..7ae63258dbc 100644 --- a/tests/Functional/JsonApi/NetworkPathTest.php +++ b/tests/Functional/JsonApi/NetworkPathTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\NetworkPathDummy; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\NetworkPathRelationDummy; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/NonResourceTest.php b/tests/Functional/JsonApi/NonResourceTest.php index 9f925752f6d..6baf8194d40 100644 --- a/tests/Functional/JsonApi/NonResourceTest.php +++ b/tests/Functional/JsonApi/NonResourceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\NonRelationResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\NonResourceContainer; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\PlainObjectResource; diff --git a/tests/Functional/JsonApi/OrderingTest.php b/tests/Functional/JsonApi/OrderingTest.php index dbd6ca7480b..313be775b7c 100644 --- a/tests/Functional/JsonApi/OrderingTest.php +++ b/tests/Functional/JsonApi/OrderingTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\OrderingDummy; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/PaginationTest.php b/tests/Functional/JsonApi/PaginationTest.php index a57eaff9368..2ac47dbca6e 100644 --- a/tests/Functional/JsonApi/PaginationTest.php +++ b/tests/Functional/JsonApi/PaginationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonApi\PaginationDummy; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php b/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php index b12ab711bfe..9468701f75f 100644 --- a/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php +++ b/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonApi; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyGroup; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProperty; diff --git a/tests/Functional/JsonLd/AbsolutePaginationTest.php b/tests/Functional/JsonLd/AbsolutePaginationTest.php index d117647a7e0..6074f3cf358 100644 --- a/tests/Functional/JsonLd/AbsolutePaginationTest.php +++ b/tests/Functional/JsonLd/AbsolutePaginationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\AbsolutePagedResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/AbsoluteUrlTest.php b/tests/Functional/JsonLd/AbsoluteUrlTest.php index e94c2e5ce35..dee4be6154e 100644 --- a/tests/Functional/JsonLd/AbsoluteUrlTest.php +++ b/tests/Functional/JsonLd/AbsoluteUrlTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\AbsoluteUrlChild; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\AbsoluteUrlParent; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/ContextOutputTest.php b/tests/Functional/JsonLd/ContextOutputTest.php index 07a6f4f9c82..fb9dba624b2 100644 --- a/tests/Functional/JsonLd/ContextOutputTest.php +++ b/tests/Functional/JsonLd/ContextOutputTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\GenIdFalse; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6810\JsonLdContextOutput; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/ContextTest.php b/tests/Functional/JsonLd/ContextTest.php index dd768a9cf55..83764d4d60c 100644 --- a/tests/Functional/JsonLd/ContextTest.php +++ b/tests/Functional/JsonLd/ContextTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\JsonLdContextDummy; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\JsonLdContextRelation; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/CursorPaginationTest.php b/tests/Functional/JsonLd/CursorPaginationTest.php index dfa41f81198..56f84c67d8e 100644 --- a/tests/Functional/JsonLd/CursorPaginationTest.php +++ b/tests/Functional/JsonLd/CursorPaginationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SoMany; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/DisableIdGenerationTest.php b/tests/Functional/JsonLd/DisableIdGenerationTest.php index d0d9759bc27..7be7b49c3ce 100644 --- a/tests/Functional/JsonLd/DisableIdGenerationTest.php +++ b/tests/Functional/JsonLd/DisableIdGenerationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\DisableIdGenAnonymous; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/EntityClassWithDateTimeTest.php b/tests/Functional/JsonLd/EntityClassWithDateTimeTest.php index 5163f098908..14a7f1c1d1d 100644 --- a/tests/Functional/JsonLd/EntityClassWithDateTimeTest.php +++ b/tests/Functional/JsonLd/EntityClassWithDateTimeTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\EntityClassWithDateTime; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\EntityClassWithDateTime as EntityClassWithDateTimeEntity; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/JsonLd/EntrypointTest.php b/tests/Functional/JsonLd/EntrypointTest.php index 502f464557a..9f63ead3d7e 100644 --- a/tests/Functional/JsonLd/EntrypointTest.php +++ b/tests/Functional/JsonLd/EntrypointTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\JsonLdContextDummy; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\JsonLdContextRelation; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/GenIdFalseTest.php b/tests/Functional/JsonLd/GenIdFalseTest.php index 7cedc762669..b9d9ebca5cd 100644 --- a/tests/Functional/JsonLd/GenIdFalseTest.php +++ b/tests/Functional/JsonLd/GenIdFalseTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\AggregateRating; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\GenIdFalse; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\LevelFirst; diff --git a/tests/Functional/JsonLd/HydraCollectionTest.php b/tests/Functional/JsonLd/HydraCollectionTest.php index e97add70b24..40db9a09eba 100644 --- a/tests/Functional/JsonLd/HydraCollectionTest.php +++ b/tests/Functional/JsonLd/HydraCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\CollectionNoPrefix; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\CollectionPagedResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\PaginationCapped; diff --git a/tests/Functional/JsonLd/HydraDocsTest.php b/tests/Functional/JsonLd/HydraDocsTest.php index 92bcd766405..dbef89ac70a 100644 --- a/tests/Functional/JsonLd/HydraDocsTest.php +++ b/tests/Functional/JsonLd/HydraDocsTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\HydraDocsDeprecated; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\HydraDocsRelated; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\HydraDocsResource; diff --git a/tests/Functional/JsonLd/HydraErrorTest.php b/tests/Functional/JsonLd/HydraErrorTest.php index aadfdf41f6e..c21b3c2f1fa 100644 --- a/tests/Functional/JsonLd/HydraErrorTest.php +++ b/tests/Functional/JsonLd/HydraErrorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\HydraErrorResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/HydraHideFromDocsTest.php b/tests/Functional/JsonLd/HydraHideFromDocsTest.php index c8806f883dd..8aae4c213c9 100644 --- a/tests/Functional/JsonLd/HydraHideFromDocsTest.php +++ b/tests/Functional/JsonLd/HydraHideFromDocsTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\HideHydraClass; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\HideHydraOperation; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/InheritanceIriTest.php b/tests/Functional/JsonLd/InheritanceIriTest.php index 1e1e415d610..4d1245436b5 100644 --- a/tests/Functional/JsonLd/InheritanceIriTest.php +++ b/tests/Functional/JsonLd/InheritanceIriTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5438\Contractor; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5438\Employee; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5438\Person; diff --git a/tests/Functional/JsonLd/InitializeInputTest.php b/tests/Functional/JsonLd/InitializeInputTest.php index 50f3b374a8d..900fac1a7d1 100644 --- a/tests/Functional/JsonLd/InitializeInputTest.php +++ b/tests/Functional/JsonLd/InitializeInputTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\InitializeInput; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/InputDtoIriDenormalizationTest.php b/tests/Functional/JsonLd/InputDtoIriDenormalizationTest.php index 4d31a832a83..9d4d39e7e92 100644 --- a/tests/Functional/JsonLd/InputDtoIriDenormalizationTest.php +++ b/tests/Functional/JsonLd/InputDtoIriDenormalizationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6465\Bar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6465\Foo; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/JsonLd/InputOutputDtoTest.php b/tests/Functional/JsonLd/InputOutputDtoTest.php index e52474d0f82..9e7f523c821 100644 --- a/tests/Functional/JsonLd/InputOutputDtoTest.php +++ b/tests/Functional/JsonLd/InputOutputDtoTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\CustomInputResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\CustomOutputResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\DummyCollectionDto; diff --git a/tests/Functional/JsonLd/InterfaceAsResourceTest.php b/tests/Functional/JsonLd/InterfaceAsResourceTest.php index 2875224c575..7c8d63fb6e7 100644 --- a/tests/Functional/JsonLd/InterfaceAsResourceTest.php +++ b/tests/Functional/JsonLd/InterfaceAsResourceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\InterfaceTaxon; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\InterfaceTaxonProduct; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/InterfaceDtoOutputTest.php b/tests/Functional/JsonLd/InterfaceDtoOutputTest.php index b34cb9a602d..0b41e76ad55 100644 --- a/tests/Functional/JsonLd/InterfaceDtoOutputTest.php +++ b/tests/Functional/JsonLd/InterfaceDtoOutputTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\InterfaceDtoOutputResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/IriOnlyTest.php b/tests/Functional/JsonLd/IriOnlyTest.php index 723d24b3d16..796d3084c43 100644 --- a/tests/Functional/JsonLd/IriOnlyTest.php +++ b/tests/Functional/JsonLd/IriOnlyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\IriOnlyResource; use ApiPlatform\Tests\SetupClassResourcesTrait; use PHPUnit\Framework\Attributes\DataProvider; diff --git a/tests/Functional/JsonLd/ItemUriTemplateCollectionTest.php b/tests/Functional/JsonLd/ItemUriTemplateCollectionTest.php index 0f6f4df5ae1..4c74c450fa1 100644 --- a/tests/Functional/JsonLd/ItemUriTemplateCollectionTest.php +++ b/tests/Functional/JsonLd/ItemUriTemplateCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ItemUriTemplateWithCollection\Recipe; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ItemUriTemplateWithCollection\RecipeCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Recipe as EntityRecipe; diff --git a/tests/Functional/JsonLd/ItemUriTemplateHydraTest.php b/tests/Functional/JsonLd/ItemUriTemplateHydraTest.php index 3646a55397e..144840d8fe8 100644 --- a/tests/Functional/JsonLd/ItemUriTemplateHydraTest.php +++ b/tests/Functional/JsonLd/ItemUriTemplateHydraTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\UriTemplateCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CollectionReferencingItem; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5662\Book; diff --git a/tests/Functional/JsonLd/ItemUriTemplateNotFoundTest.php b/tests/Functional/JsonLd/ItemUriTemplateNotFoundTest.php index b40907860c1..92c115325c1 100644 --- a/tests/Functional/JsonLd/ItemUriTemplateNotFoundTest.php +++ b/tests/Functional/JsonLd/ItemUriTemplateNotFoundTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6718\Organization; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/JsonSerializableTest.php b/tests/Functional/JsonLd/JsonSerializableTest.php index f859f9a562a..10138bd3f8a 100644 --- a/tests/Functional/JsonLd/JsonSerializableTest.php +++ b/tests/Functional/JsonLd/JsonSerializableTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\JsonSerializableResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/LinkedDataPlatformTest.php b/tests/Functional/JsonLd/LinkedDataPlatformTest.php index 5ad112b61c3..b16a10de2d4 100644 --- a/tests/Functional/JsonLd/LinkedDataPlatformTest.php +++ b/tests/Functional/JsonLd/LinkedDataPlatformTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\DummyGetPostDeleteOperation; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/MaxDepthTest.php b/tests/Functional/JsonLd/MaxDepthTest.php index c5b0501475e..ef589dd6035 100644 --- a/tests/Functional/JsonLd/MaxDepthTest.php +++ b/tests/Functional/JsonLd/MaxDepthTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\MaxDepthResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/MessengerTest.php b/tests/Functional/JsonLd/MessengerTest.php index 0a3f0c7e560..bf296e8576a 100644 --- a/tests/Functional/JsonLd/MessengerTest.php +++ b/tests/Functional/JsonLd/MessengerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MessengerWithInput; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MessengerWithResponse; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/MultiResourceContextTest.php b/tests/Functional/JsonLd/MultiResourceContextTest.php index ed729866cb2..4e7f4e46ae0 100644 --- a/tests/Functional/JsonLd/MultiResourceContextTest.php +++ b/tests/Functional/JsonLd/MultiResourceContextTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MultiResourceEntity; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/NetworkPathTest.php b/tests/Functional/JsonLd/NetworkPathTest.php index b8b946115ec..fa18dc91a68 100644 --- a/tests/Functional/JsonLd/NetworkPathTest.php +++ b/tests/Functional/JsonLd/NetworkPathTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\NetworkPathParent; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\NetworkPathResource; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/NoOutputTest.php b/tests/Functional/JsonLd/NoOutputTest.php index c9bff3750e8..33a99322b59 100644 --- a/tests/Functional/JsonLd/NoOutputTest.php +++ b/tests/Functional/JsonLd/NoOutputTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\NoOutputMessage; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonLd/NonResourceTest.php b/tests/Functional/JsonLd/NonResourceTest.php index 941a1065e9e..a3bc4d19475 100644 --- a/tests/Functional/JsonLd/NonResourceTest.php +++ b/tests/Functional/JsonLd/NonResourceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\DateTimeOnlyResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\GenIdFalseProperty; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\NonRelationResource; diff --git a/tests/Functional/JsonLd/PolymorphicResourceCollectionTest.php b/tests/Functional/JsonLd/PolymorphicResourceCollectionTest.php index d1f28bb4437..96eaaa2e03a 100644 --- a/tests/Functional/JsonLd/PolymorphicResourceCollectionTest.php +++ b/tests/Functional/JsonLd/PolymorphicResourceCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7298\ImageModuleResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7298\PageResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7298\TitleModuleResource; diff --git a/tests/Functional/JsonLd/PropertyCollectionIriOnlyTest.php b/tests/Functional/JsonLd/PropertyCollectionIriOnlyTest.php index ec5f3dce0e7..d4f160e179a 100644 --- a/tests/Functional/JsonLd/PropertyCollectionIriOnlyTest.php +++ b/tests/Functional/JsonLd/PropertyCollectionIriOnlyTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnly; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnlyRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PropertyCollectionIriOnlyRelationSecondLevel; diff --git a/tests/Functional/JsonLd/RenamedGetterSetterTest.php b/tests/Functional/JsonLd/RenamedGetterSetterTest.php index 1f08a5818cb..cc0e45a7ca2 100644 --- a/tests/Functional/JsonLd/RenamedGetterSetterTest.php +++ b/tests/Functional/JsonLd/RenamedGetterSetterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\JsonLd; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonLd\RenamedGetterSetter; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php b/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php index a9c3f3533af..0bf88cea92c 100644 --- a/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php +++ b/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php @@ -16,7 +16,7 @@ use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Animal; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\AnimalObservation; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6317\Issue6317; diff --git a/tests/Functional/JsonSchema/JsonLdJsonSchemaTest.php b/tests/Functional/JsonSchema/JsonLdJsonSchemaTest.php index a8ea9f28ac7..48eb605d8c3 100644 --- a/tests/Functional/JsonSchema/JsonLdJsonSchemaTest.php +++ b/tests/Functional/JsonSchema/JsonLdJsonSchemaTest.php @@ -15,7 +15,7 @@ use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7426\Boat; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5793\BagOfTests; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6212\Nest; diff --git a/tests/Functional/JsonSchema/JsonSchemaTest.php b/tests/Functional/JsonSchema/JsonSchemaTest.php index da2da4d87bd..d6d5d12baad 100644 --- a/tests/Functional/JsonSchema/JsonSchemaTest.php +++ b/tests/Functional/JsonSchema/JsonSchemaTest.php @@ -16,8 +16,8 @@ use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; -use ApiPlatform\Symfony\Bundle\Test\Constraint\MatchesJsonSchema; +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Test\Constraint\MatchesJsonSchema; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\AggregateRating; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ChildAttribute; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5452\Book; diff --git a/tests/Functional/JsonSchema/JsonSchemaWithDefaultParametersTest.php b/tests/Functional/JsonSchema/JsonSchemaWithDefaultParametersTest.php index 08a72968989..584aa23db53 100644 --- a/tests/Functional/JsonSchema/JsonSchemaWithDefaultParametersTest.php +++ b/tests/Functional/JsonSchema/JsonSchemaWithDefaultParametersTest.php @@ -15,7 +15,7 @@ use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5793\BagOfTests; /** diff --git a/tests/Functional/JsonStreamerTest.php b/tests/Functional/JsonStreamerTest.php index 92749003e82..17b414b1152 100644 --- a/tests/Functional/JsonStreamerTest.php +++ b/tests/Functional/JsonStreamerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\AggregateRating; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Product; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\JsonStreamResource; diff --git a/tests/Functional/ListenerTest.php b/tests/Functional/ListenerTest.php index 71488e78259..d787a0f56d8 100644 --- a/tests/Functional/ListenerTest.php +++ b/tests/Functional/ListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7432\OriginalDataWithListeners; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/MappingTest.php b/tests/Functional/MappingTest.php index 353153b9f69..21eca4b06cb 100644 --- a/tests/Functional/MappingTest.php +++ b/tests/Functional/MappingTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\BookStoreResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\FirstResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7563\BookDto; diff --git a/tests/Functional/MathNumberTest.php b/tests/Functional/MathNumberTest.php index 04dab45903a..03666455e88 100644 --- a/tests/Functional/MathNumberTest.php +++ b/tests/Functional/MathNumberTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MathNumber; use ApiPlatform\Tests\SetupClassResourcesTrait; use PHPUnit\Framework\Attributes\RequiresPhp; diff --git a/tests/Functional/McpTest.php b/tests/Functional/McpTest.php index 5cff5220061..9ce3240909a 100644 --- a/tests/Functional/McpTest.php +++ b/tests/Functional/McpTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\McpResourceExample; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\McpToolAttribute; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\McpTools; diff --git a/tests/Functional/Mercure/MercureTest.php b/tests/Functional/Mercure/MercureTest.php new file mode 100644 index 00000000000..5471f13baf7 --- /dev/null +++ b/tests/Functional/Mercure/MercureTest.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\Mercure; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyMercure; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5074\MercureWithTopics; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MercureWithTopicsAndGetOperation; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Mercure\TestHub; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; +use Symfony\Component\Mercure\Update; + +final class MercureTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [ + DummyMercure::class, + RelatedDummy::class, + MercureWithTopics::class, + MercureWithTopicsAndGetOperation::class, + ]; + } + + public function testDiscoveryLinkOnMercureResource(): void + { + $this->recreateSchema([DummyMercure::class, RelatedDummy::class]); + + $response = self::createClient()->request('GET', '/dummy_mercures', [ + 'headers' => ['Accept' => 'application/ld+json'], + ]); + + $this->assertContains( + '; rel="mercure"', + $response->getHeaders()['link'], + ); + } + + public function testNoDiscoveryLinkOnNonMercureEndpoint(): void + { + $response = self::createClient()->request('GET', '/'); + + $this->assertNotContains( + '; rel="mercure"', + $response->getHeaders()['link'] ?? [], + ); + } + + public function testPublishUpdateOnPostWithIriTopic(): void + { + $this->recreateSchema([MercureWithTopics::class]); + $hub = $this->resetTestHub(); + + self::createClient()->request('POST', '/issue5074/mercure_with_topics', [ + 'headers' => [ + 'Accept' => 'application/ld+json', + 'Content-Type' => 'application/ld+json', + ], + 'json' => [ + 'name' => 'Hello World!', + 'description' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + ], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + + $updates = $hub->getUpdates(); + $this->assertCount(1, $updates); + /** @var Update $update */ + $update = $updates[0]; + $this->assertSame(['http://localhost/issue5074/mercure_with_topics/1'], array_values($update->getTopics())); + $this->assertJsonStringEqualsJsonString( + json_encode([ + '@context' => '/contexts/MercureWithTopics', + '@id' => '/issue5074/mercure_with_topics/1', + '@type' => 'MercureWithTopics', + 'id' => 1, + 'name' => 'Hello World!', + ], \JSON_THROW_ON_ERROR), + $update->getData(), + ); + } + + public function testPublishUpdateWithExpressionLanguageTopics(): void + { + $this->recreateSchema([MercureWithTopicsAndGetOperation::class]); + $hub = $this->resetTestHub(); + + self::createClient()->request('POST', '/mercure_with_topics_and_get_operations', [ + 'headers' => [ + 'Accept' => 'application/ld+json', + 'Content-Type' => 'application/ld+json', + ], + 'json' => ['name' => 'Hello World!'], + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + + $updates = $hub->getUpdates(); + $this->assertCount(1, $updates); + /** @var Update $update */ + $update = $updates[0]; + $this->assertSame([ + 'http://localhost/mercure_with_topics_and_get_operations/1', + 'http://localhost/custom_resource/mercure_with_topics_and_get_operations/1', + ], array_values($update->getTopics())); + $this->assertJsonStringEqualsJsonString( + json_encode([ + '@context' => '/contexts/MercureWithTopicsAndGetOperation', + '@id' => '/mercure_with_topics_and_get_operations/1', + '@type' => 'MercureWithTopicsAndGetOperation', + 'id' => 1, + 'name' => 'Hello World!', + ], \JSON_THROW_ON_ERROR), + $update->getData(), + ); + } + + private function resetTestHub(): TestHub + { + $hub = static::getContainer()->get('mercure.hub.default.test_hub'); + \assert($hub instanceof TestHub); + + $reflection = new \ReflectionProperty(TestHub::class, 'updates'); + $reflection->setValue($hub, []); + + return $hub; + } +} diff --git a/tests/Functional/MultipleResourceEntrypointTest.php b/tests/Functional/MultipleResourceEntrypointTest.php index 0277946deee..f664f1a1834 100644 --- a/tests/Functional/MultipleResourceEntrypointTest.php +++ b/tests/Functional/MultipleResourceEntrypointTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\MultipleResourceBook; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/NestedFilterTest.php b/tests/Functional/NestedFilterTest.php index c34bb770e75..cc525589afd 100644 --- a/tests/Functional/NestedFilterTest.php +++ b/tests/Functional/NestedFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilterNestedTest\FilterCompany; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilterNestedTest\FilterDepartment; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilterNestedTest\FilterEmployee; diff --git a/tests/Functional/NestedPatchTest.php b/tests/Functional/NestedPatchTest.php index c39485e9ad5..c89719008ae 100644 --- a/tests/Functional/NestedPatchTest.php +++ b/tests/Functional/NestedPatchTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Camp; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6225\Bar6225; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue6225\Foo6225; diff --git a/tests/Functional/NotSkipNullToOneRelationTest.php b/tests/Functional/NotSkipNullToOneRelationTest.php index c6943383d0c..e49a16172d7 100644 --- a/tests/Functional/NotSkipNullToOneRelationTest.php +++ b/tests/Functional/NotSkipNullToOneRelationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue4372\RelatedEntity; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue4372\ToOneRelationPropertyMayBeNull; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/NullOnNonNullablePropertyTest.php b/tests/Functional/NullOnNonNullablePropertyTest.php new file mode 100644 index 00000000000..3fba229b205 --- /dev/null +++ b/tests/Functional/NullOnNonNullablePropertyTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\NullOnNonNullableProperty\NullOnNonNullableResource; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +/** @see https://github.com/symfony/symfony/issues/64159 */ +final class NullOnNonNullablePropertyTest extends ApiTestCase +{ + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + /** + * @return class-string[] + */ + public static function getResources(): array + { + return [NullOnNonNullableResource::class]; + } + + public function testNullOnNonNullablePropertyReturns400(): void + { + $response = self::createClient()->request('POST', '/null_on_non_nullable_resources', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['name' => null], + ]); + + $this->assertResponseStatusCodeSame(400); + $this->assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); + $body = $response->toArray(false); + $this->assertStringContainsString('Expected argument of type "string", "null" given at property path "name"', $body['hydra:description'] ?? $body['detail'] ?? ''); + } + + public function testNullOnNonNullablePropertyReturns422WhenCollectingErrors(): void + { + $response = self::createClient()->request('POST', '/null_on_non_nullable_resources_collect', [ + 'headers' => ['Content-Type' => 'application/ld+json'], + 'json' => ['name' => null], + ]); + + $this->assertResponseStatusCodeSame(422); + $this->assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8'); + + $content = $response->toArray(false); + $this->assertArrayHasKey('violations', $content); + $this->assertSame('name', $content['violations'][0]['propertyPath']); + } +} diff --git a/tests/Functional/ObjectMapperValidationTest.php b/tests/Functional/ObjectMapperValidationTest.php index 8726a3a4476..ecfdf7f4e4e 100644 --- a/tests/Functional/ObjectMapperValidationTest.php +++ b/tests/Functional/ObjectMapperValidationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\UniqueBookResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UniqueBook; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/OpenApiTest.php b/tests/Functional/OpenApiTest.php index 1bfbe5f7496..cd4d58a62f9 100644 --- a/tests/Functional/OpenApiTest.php +++ b/tests/Functional/OpenApiTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ChildAttribute; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Crud; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\CrudOpenApiApiPlatformTag; diff --git a/tests/Functional/PaginationDisabledTest.php b/tests/Functional/PaginationDisabledTest.php index 3fc59db32fe..e503b99e951 100644 --- a/tests/Functional/PaginationDisabledTest.php +++ b/tests/Functional/PaginationDisabledTest.php @@ -15,7 +15,7 @@ use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PaginationDisabledEntity; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Parameters/BooleanFilterTest.php b/tests/Functional/Parameters/BooleanFilterTest.php index a856ea33790..f1a9ffeef41 100644 --- a/tests/Functional/Parameters/BooleanFilterTest.php +++ b/tests/Functional/Parameters/BooleanFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilteredBooleanParameter as FilteredBooleanParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilteredBooleanParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/BooleanQueryParameterDefaultTest.php b/tests/Functional/Parameters/BooleanQueryParameterDefaultTest.php index ded635de0d9..d705b2750b3 100644 --- a/tests/Functional/Parameters/BooleanQueryParameterDefaultTest.php +++ b/tests/Functional/Parameters/BooleanQueryParameterDefaultTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\BooleanQueryParameterDefault\BooleanQueryParameterDefault; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Parameters/ComparisonFilterTest.php b/tests/Functional/Parameters/ComparisonFilterTest.php index 8caaef1e3dd..9f776e51b51 100644 --- a/tests/Functional/Parameters/ComparisonFilterTest.php +++ b/tests/Functional/Parameters/ComparisonFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Chicken as DocumentChicken; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ChickenCoop as DocumentChickenCoop; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Owner as DocumentOwner; diff --git a/tests/Functional/Parameters/DateFilterTest.php b/tests/Functional/Parameters/DateFilterTest.php index 72c90d214ef..c31f903b086 100644 --- a/tests/Functional/Parameters/DateFilterTest.php +++ b/tests/Functional/Parameters/DateFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilteredDateParameter as FilteredDateParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilteredDateParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/DoctrineTest.php b/tests/Functional/Parameters/DoctrineTest.php index abce8d43447..581f101df09 100644 --- a/tests/Functional/Parameters/DoctrineTest.php +++ b/tests/Functional/Parameters/DoctrineTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\FilterWithStateOptions; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\FilterWithStateOptionsAndNoApiFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SearchFilterParameter as SearchFilterParameterDocument; diff --git a/tests/Functional/Parameters/EmbeddedPartialSearchFilterTest.php b/tests/Functional/Parameters/EmbeddedPartialSearchFilterTest.php index 54b8833a991..34aab02658f 100644 --- a/tests/Functional/Parameters/EmbeddedPartialSearchFilterTest.php +++ b/tests/Functional/Parameters/EmbeddedPartialSearchFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\PostCard as DocumentPostCard; use ApiPlatform\Tests\Fixtures\TestBundle\Document\PostCardAddress as DocumentPostCardAddress; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\PostCard; diff --git a/tests/Functional/Parameters/ExactFilterTest.php b/tests/Functional/Parameters/ExactFilterTest.php index 534163f081e..2aa34705813 100644 --- a/tests/Functional/Parameters/ExactFilterTest.php +++ b/tests/Functional/Parameters/ExactFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Chicken as DocumentChicken; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ChickenCoop as DocumentChickenCoop; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Owner as DocumentOwner; diff --git a/tests/Functional/Parameters/ExistsFilterTest.php b/tests/Functional/Parameters/ExistsFilterTest.php index 122854154bf..bd07757fea6 100644 --- a/tests/Functional/Parameters/ExistsFilterTest.php +++ b/tests/Functional/Parameters/ExistsFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilteredExistsParameter as FilteredExistsParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilteredExistsParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/FreeTextQueryFilterNestedTest.php b/tests/Functional/Parameters/FreeTextQueryFilterNestedTest.php index fa7e8f84b85..ef59b98b1e0 100644 --- a/tests/Functional/Parameters/FreeTextQueryFilterNestedTest.php +++ b/tests/Functional/Parameters/FreeTextQueryFilterNestedTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FreeTextArticle as DocumentFreeTextArticle; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FreeTextTag as DocumentFreeTextTag; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FreeTextArticle; diff --git a/tests/Functional/Parameters/FreeTextQueryFilterTest.php b/tests/Functional/Parameters/FreeTextQueryFilterTest.php index 31e051b51f6..64108162524 100644 --- a/tests/Functional/Parameters/FreeTextQueryFilterTest.php +++ b/tests/Functional/Parameters/FreeTextQueryFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Chicken as DocumentChicken; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ChickenCoop as DocumentChickenCoop; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Owner as DocumentOwner; diff --git a/tests/Functional/Parameters/HydraTest.php b/tests/Functional/Parameters/HydraTest.php index f2a29361ca9..bdd1ea9a973 100644 --- a/tests/Functional/Parameters/HydraTest.php +++ b/tests/Functional/Parameters/HydraTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\WithParameter; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Parameters/IriFilterRelationsTest.php b/tests/Functional/Parameters/IriFilterRelationsTest.php index cf050a02dfe..350054bbb39 100644 --- a/tests/Functional/Parameters/IriFilterRelationsTest.php +++ b/tests/Functional/Parameters/IriFilterRelationsTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\IriFilterRelationsTest\Author; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\IriFilterRelationsTest\Biography; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\IriFilterRelationsTest\Book; diff --git a/tests/Functional/Parameters/IriFilterTest.php b/tests/Functional/Parameters/IriFilterTest.php index d91537ce0a8..e91ecb88b08 100644 --- a/tests/Functional/Parameters/IriFilterTest.php +++ b/tests/Functional/Parameters/IriFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Chicken as DocumentChicken; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ChickenCoop as DocumentChickenCoop; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Chicken; diff --git a/tests/Functional/Parameters/IriProviderParameterTest.php b/tests/Functional/Parameters/IriProviderParameterTest.php index f878c43b0ee..ece9ed547ea 100644 --- a/tests/Functional/Parameters/IriProviderParameterTest.php +++ b/tests/Functional/Parameters/IriProviderParameterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\WithParameter; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/Issue7913IriFilterCustomIdentifierTest.php b/tests/Functional/Parameters/Issue7913IriFilterCustomIdentifierTest.php index c4d02ed3c74..39fe8635e03 100644 --- a/tests/Functional/Parameters/Issue7913IriFilterCustomIdentifierTest.php +++ b/tests/Functional/Parameters/Issue7913IriFilterCustomIdentifierTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Issue7913\Agent as DocumentAgent; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Issue7913\Mail as DocumentMail; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/Issue7916NestedFilterOnNonResourceTest.php b/tests/Functional/Parameters/Issue7916NestedFilterOnNonResourceTest.php index 77f0240aa55..63f19f01c48 100644 --- a/tests/Functional/Parameters/Issue7916NestedFilterOnNonResourceTest.php +++ b/tests/Functional/Parameters/Issue7916NestedFilterOnNonResourceTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7916\UserActionResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7916\UserActionResourceOdm; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7916\UserResource; diff --git a/tests/Functional/Parameters/LinkProviderParameterTest.php b/tests/Functional/Parameters/LinkProviderParameterTest.php index cd7ef7d5a4e..cda462cafc6 100644 --- a/tests/Functional/Parameters/LinkProviderParameterTest.php +++ b/tests/Functional/Parameters/LinkProviderParameterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7469TestResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7939BarResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7939BazResource; diff --git a/tests/Functional/Parameters/NameConverterFilterTest.php b/tests/Functional/Parameters/NameConverterFilterTest.php index 4b65c321d13..327d76cd6f1 100644 --- a/tests/Functional/Parameters/NameConverterFilterTest.php +++ b/tests/Functional/Parameters/NameConverterFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ConvertedDateParameter as ConvertedDateParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConvertedDateParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/NestedNonResourceRelationFilterTest.php b/tests/Functional/Parameters/NestedNonResourceRelationFilterTest.php index 9954c6a239c..251c671a8eb 100644 --- a/tests/Functional/Parameters/NestedNonResourceRelationFilterTest.php +++ b/tests/Functional/Parameters/NestedNonResourceRelationFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\NonResourceRelation as DocumentNonResourceRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ResourceWithNonResourceRelation as DocumentResourceWithNonResourceRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\NonResourceRelation; diff --git a/tests/Functional/Parameters/NumericFilterTest.php b/tests/Functional/Parameters/NumericFilterTest.php index 03512ac1462..e1b6524cbf8 100644 --- a/tests/Functional/Parameters/NumericFilterTest.php +++ b/tests/Functional/Parameters/NumericFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilteredNumericParameter as FilteredNumericParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilteredNumericParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/OrFilterTest.php b/tests/Functional/Parameters/OrFilterTest.php index cc0893e3dc6..57f56f9c253 100644 --- a/tests/Functional/Parameters/OrFilterTest.php +++ b/tests/Functional/Parameters/OrFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Chicken as DocumentChicken; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ChickenCoop as DocumentChickenCoop; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Chicken; diff --git a/tests/Functional/Parameters/OrderFilterTest.php b/tests/Functional/Parameters/OrderFilterTest.php index 368ca970289..54ed88ea16d 100644 --- a/tests/Functional/Parameters/OrderFilterTest.php +++ b/tests/Functional/Parameters/OrderFilterTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilteredOrderParameter as FilteredOrderParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilteredOrderParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/ParameterProviderTest.php b/tests/Functional/Parameters/ParameterProviderTest.php index 89b95914fdf..2fdb75364aa 100644 --- a/tests/Functional/Parameters/ParameterProviderTest.php +++ b/tests/Functional/Parameters/ParameterProviderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6673\MutlipleParameterProvider; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Parameters/ParameterTest.php b/tests/Functional/Parameters/ParameterTest.php index 6a0ef794261..32dd657598a 100644 --- a/tests/Functional/Parameters/ParameterTest.php +++ b/tests/Functional/Parameters/ParameterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\TranslateValidationError; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\WithParameter; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Parameters/PartialSearchFilterTest.php b/tests/Functional/Parameters/PartialSearchFilterTest.php index 3a2bebe66da..f681d52d3e2 100644 --- a/tests/Functional/Parameters/PartialSearchFilterTest.php +++ b/tests/Functional/Parameters/PartialSearchFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Chicken as DocumentChicken; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ChickenCoop as DocumentChickenCoop; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Owner as DocumentOwner; diff --git a/tests/Functional/Parameters/QueryParameterStateOptionsTest.php b/tests/Functional/Parameters/QueryParameterStateOptionsTest.php index 6c2cdd384e5..bc0b34ec339 100644 --- a/tests/Functional/Parameters/QueryParameterStateOptionsTest.php +++ b/tests/Functional/Parameters/QueryParameterStateOptionsTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\AgentApi; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResourceOdm\AgentDocumentApi; use ApiPlatform\Tests\Fixtures\TestBundle\Document\AgentDocument; diff --git a/tests/Functional/Parameters/RangeFilterTest.php b/tests/Functional/Parameters/RangeFilterTest.php index 0ad31aa5c29..82a32fec6ff 100644 --- a/tests/Functional/Parameters/RangeFilterTest.php +++ b/tests/Functional/Parameters/RangeFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilteredRangeParameter as FilteredRangeParameterDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FilteredRangeParameter; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Parameters/SecurityTest.php b/tests/Functional/Parameters/SecurityTest.php index 955c9cb7a96..77345c4ff27 100644 --- a/tests/Functional/Parameters/SecurityTest.php +++ b/tests/Functional/Parameters/SecurityTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\WithSecurityParameter; use ApiPlatform\Tests\SetupClassResourcesTrait; use PHPUnit\Framework\Attributes\DataProvider; diff --git a/tests/Functional/Parameters/SortFilterTest.php b/tests/Functional/Parameters/SortFilterTest.php index fb0bad15f97..4b6bc47bd33 100644 --- a/tests/Functional/Parameters/SortFilterTest.php +++ b/tests/Functional/Parameters/SortFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilterNestedTest\FilterCompany as DocumentFilterCompany; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilterNestedTest\FilterDepartment as DocumentFilterDepartment; use ApiPlatform\Tests\Fixtures\TestBundle\Document\FilterNestedTest\FilterEmployee as DocumentFilterEmployee; diff --git a/tests/Functional/Parameters/StrictParametersTest.php b/tests/Functional/Parameters/StrictParametersTest.php index 3a973b8338c..22152665800 100644 --- a/tests/Functional/Parameters/StrictParametersTest.php +++ b/tests/Functional/Parameters/StrictParametersTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\StrictParameters; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Parameters/ValidationTest.php b/tests/Functional/Parameters/ValidationTest.php index 7c243edd679..d5067a3b6fa 100644 --- a/tests/Functional/Parameters/ValidationTest.php +++ b/tests/Functional/Parameters/ValidationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Parameters; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\TranslateValidationError; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ValidateParameterBeforeProvider; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\WithParameter; diff --git a/tests/Functional/SecurityPropertyInputDtoTest.php b/tests/Functional/SecurityPropertyInputDtoTest.php index cbbef5d9141..a62a977a468 100644 --- a/tests/Functional/SecurityPropertyInputDtoTest.php +++ b/tests/Functional/SecurityPropertyInputDtoTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\DummyDtoSecuredInput; use ApiPlatform\Tests\SetupClassResourcesTrait; use Symfony\Component\Security\Core\User\InMemoryUser; diff --git a/tests/Functional/SubResource/MultipleRelationTest.php b/tests/Functional/SubResource/MultipleRelationTest.php new file mode 100644 index 00000000000..e0be9698fd9 --- /dev/null +++ b/tests/Functional/SubResource/MultipleRelationTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\SubResource; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelationMultiple; +use ApiPlatform\Tests\SetupClassResourcesTrait; + +final class MultipleRelationTest extends ApiTestCase +{ + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [RelationMultiple::class, Dummy::class]; + } + + public function testGetMultipleRelationItem(): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped(); + } + + self::createClient()->request('GET', '/dummy/1/relations/2', [ + 'headers' => ['Accept' => 'application/ld+json'], + ]); + + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + $this->assertJsonEquals([ + '@context' => '/contexts/RelationMultiple', + '@id' => '/dummy/1/relations/2', + '@type' => 'RelationMultiple', + 'id' => 1, + 'first' => '/dummies/1', + 'second' => '/dummies/2', + ]); + } + + public function testGetMultipleRelationCollection(): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped(); + } + + self::createClient()->request('GET', '/dummy/1/relations', [ + 'headers' => ['Accept' => 'application/ld+json'], + ]); + + $this->assertResponseStatusCodeSame(200); + $this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8'); + $this->assertJsonEquals([ + '@context' => '/contexts/RelationMultiple', + '@id' => '/dummy/1/relations', + '@type' => 'hydra:Collection', + 'hydra:member' => [ + [ + '@id' => '/dummy/1/relations/2', + '@type' => 'RelationMultiple', + 'id' => 1, + 'first' => '/dummies/1', + 'second' => '/dummies/2', + ], + [ + '@id' => '/dummy/1/relations/3', + '@type' => 'RelationMultiple', + 'id' => 2, + 'first' => '/dummies/1', + 'second' => '/dummies/3', + ], + ], + 'hydra:totalItems' => 2, + ]); + } + + private function isMongoDB(): bool + { + return 'mongodb' === static::getContainer()->getParameter('kernel.environment'); + } +} diff --git a/tests/Functional/Uuid/UuidComparisonFilterTest.php b/tests/Functional/Uuid/UuidComparisonFilterTest.php index 016d617c706..2673d6dee39 100644 --- a/tests/Functional/Uuid/UuidComparisonFilterTest.php +++ b/tests/Functional/Uuid/UuidComparisonFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Uuid; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Uuid\SymfonyUuidDevice; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Uuid\SymfonyUuidDeviceEndpoint; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/Uuid/UuidFilterBaseTestCase.php b/tests/Functional/Uuid/UuidFilterBaseTestCase.php index 7068423e967..8cba186b5f2 100644 --- a/tests/Functional/Uuid/UuidFilterBaseTestCase.php +++ b/tests/Functional/Uuid/UuidFilterBaseTestCase.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Uuid; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/Functional/Uuid/UuidFilterWithCustomSchemaTest.php b/tests/Functional/Uuid/UuidFilterWithCustomSchemaTest.php index 3db038da67b..416feae55d5 100644 --- a/tests/Functional/Uuid/UuidFilterWithCustomSchemaTest.php +++ b/tests/Functional/Uuid/UuidFilterWithCustomSchemaTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Uuid; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Uuid\UuidFilterWithCustomSchema; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/Uuid/UuidIriRelationTest.php b/tests/Functional/Uuid/UuidIriRelationTest.php index b7252f6ee93..08274a4c329 100644 --- a/tests/Functional/Uuid/UuidIriRelationTest.php +++ b/tests/Functional/Uuid/UuidIriRelationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional\Uuid; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UuidIriRelation\Bar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UuidIriRelation\Foo; use ApiPlatform\Tests\RecreateSchemaTrait; diff --git a/tests/Functional/ValidateProcessorTest.php b/tests/Functional/ValidateProcessorTest.php index a1e0e650c88..4b32bf34cc7 100644 --- a/tests/Functional/ValidateProcessorTest.php +++ b/tests/Functional/ValidateProcessorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\ValidateOnce; use ApiPlatform\Tests\Fixtures\TestBundle\Validator\CountableConstraintValidator; use ApiPlatform\Tests\SetupClassResourcesTrait; diff --git a/tests/Functional/ValidationTest.php b/tests/Functional/ValidationTest.php index c82238d75d0..d49840f9736 100644 --- a/tests/Functional/ValidationTest.php +++ b/tests/Functional/ValidationTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Functional; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue7228\ValidationGroupSequence; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyWithCollectDenormalizationErrors; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; diff --git a/tests/Functional/Xml/DeserializationTest.php b/tests/Functional/Xml/DeserializationTest.php new file mode 100644 index 00000000000..10df4a1a2ae --- /dev/null +++ b/tests/Functional/Xml/DeserializationTest.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Functional\Xml; + +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProperty; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceWithBoolean; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceWithFloat; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceWithInteger; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceWithString; +use ApiPlatform\Tests\RecreateSchemaTrait; +use ApiPlatform\Tests\SetupClassResourcesTrait; +use PHPUnit\Framework\Attributes\DataProvider; + +final class DeserializationTest extends ApiTestCase +{ + use RecreateSchemaTrait; + use SetupClassResourcesTrait; + + protected static ?bool $alwaysBootKernel = false; + + public static function getResources(): array + { + return [ + ResourceWithString::class, + ResourceWithBoolean::class, + ResourceWithInteger::class, + ResourceWithFloat::class, + DummyProperty::class, + ]; + } + + private const XML_HEADERS = [ + 'Accept' => 'application/xml', + 'Content-Type' => 'application/xml', + ]; + + public function testPostStringResource(): void + { + $this->recreateSchema([ResourceWithString::class]); + + self::createClient()->request('POST', '/resource_with_strings', [ + 'headers' => self::XML_HEADERS, + 'body' => <<<'XML' + + + string + + XML, + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/xml; charset=utf-8'); + } + + public static function booleanValues(): iterable + { + yield ['true']; + yield ['false']; + yield ['1']; + yield ['0']; + } + + #[DataProvider('booleanValues')] + public function testPostBooleanResource(string $value): void + { + $this->recreateSchema([ResourceWithBoolean::class]); + + self::createClient()->request('POST', '/resource_with_booleans', [ + 'headers' => self::XML_HEADERS, + 'body' => \sprintf(<<<'XML' + + + %s + + XML, $value), + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/xml; charset=utf-8'); + } + + public static function integerValues(): iterable + { + yield ['42']; + yield ['-6']; + yield ['1']; + yield ['0']; + } + + #[DataProvider('integerValues')] + public function testPostIntegerResource(string $value): void + { + $this->recreateSchema([ResourceWithInteger::class]); + + self::createClient()->request('POST', '/resource_with_integers', [ + 'headers' => self::XML_HEADERS, + 'body' => \sprintf(<<<'XML' + + + %s + + XML, $value), + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/xml; charset=utf-8'); + } + + public static function floatValues(): iterable + { + yield ['3.14']; + yield ['NaN']; + yield ['INF']; + yield ['-INF']; + } + + #[DataProvider('floatValues')] + public function testPostFloatResource(string $value): void + { + if ($this->isMysql()) { + $this->markTestSkipped('MySQL does not support NaN/Inf floats'); + } + + $this->recreateSchema([ResourceWithFloat::class]); + + self::createClient()->request('POST', '/resource_with_floats', [ + 'headers' => self::XML_HEADERS, + 'body' => \sprintf(<<<'XML' + + + %s + + XML, $value), + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/xml; charset=utf-8'); + } + + public function testPostSingleElementCollection(): void + { + $this->recreateSchema([DummyProperty::class]); + + self::createClient()->request('POST', '/dummy_properties', [ + 'headers' => self::XML_HEADERS, + 'body' => <<<'XML' + + + + + bar + + + + XML, + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('Content-Type', 'application/xml; charset=utf-8'); + } +} diff --git a/tests/RecreateSchemaTrait.php b/tests/RecreateSchemaTrait.php index 7ab756e4604..a5f53cb9326 100644 --- a/tests/RecreateSchemaTrait.php +++ b/tests/RecreateSchemaTrait.php @@ -29,11 +29,18 @@ private function recreateSchema(array $classes = []): void if ($manager instanceof DocumentManager) { $schemaManager = $manager->getSchemaManager(); + $firstDocumentClass = null; foreach ($classes as $c) { $class = str_contains($c, 'Entity') ? str_replace('Entity', 'Document', $c) : $c; + $firstDocumentClass ??= $class; $schemaManager->dropDocumentCollection($class); } + // Reset INCREMENT id counters; otherwise IDs persist across test methods. + if (null !== $firstDocumentClass) { + $manager->getDocumentDatabase($firstDocumentClass)->dropCollection('doctrine_increment_ids'); + } + return; } diff --git a/tests/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Symfony/Bundle/ApiPlatformBundleTest.php index f985c963cdf..57f844672b2 100644 --- a/tests/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Symfony/Bundle/ApiPlatformBundleTest.php @@ -22,6 +22,7 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlResolverPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; +use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\JsonStreamerTransformerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MutatorPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\SerializerMappingLoaderPass; @@ -57,6 +58,7 @@ public function testBuild(): void $containerProphecy->addCompilerPass(Argument::type(AuthenticatorManagerPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(SerializerMappingLoaderPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(MutatorPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); + $containerProphecy->addCompilerPass(Argument::type(JsonStreamerTransformerPass::class), PassConfig::TYPE_BEFORE_OPTIMIZATION, -10)->willReturn($containerProphecy->reveal())->shouldBeCalled(); $bundle = new ApiPlatformBundle(); $bundle->build($containerProphecy->reveal()); diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php index 37284d9f824..3409af97d3a 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; -use ApiPlatform\Symfony\Bundle\Test\Client; +use ApiPlatform\Test\Client; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; diff --git a/tests/Symfony/Bundle/Test/ApiTestCaseTest.php b/tests/Test/ApiTestCaseTest.php similarity index 99% rename from tests/Symfony/Bundle/Test/ApiTestCaseTest.php rename to tests/Test/ApiTestCaseTest.php index 422d1e558c6..5db045361b7 100644 --- a/tests/Symfony/Bundle/Test/ApiTestCaseTest.php +++ b/tests/Test/ApiTestCaseTest.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Tests\Symfony\Bundle\Test; +namespace ApiPlatform\Tests\Test; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Test\ApiTestCase; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5921\ExceptionResource; use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\OperationPriorities; use ApiPlatform\Tests\Fixtures\TestBundle\Document\DirectMercure as DirectMercureDocument; diff --git a/tests/Symfony/Bundle/Test/ClientTest.php b/tests/Test/ClientTest.php similarity index 97% rename from tests/Symfony/Bundle/Test/ClientTest.php rename to tests/Test/ClientTest.php index 9fb196f87ce..15cebe5009d 100644 --- a/tests/Symfony/Bundle/Test/ClientTest.php +++ b/tests/Test/ClientTest.php @@ -11,10 +11,10 @@ declare(strict_types=1); -namespace ApiPlatform\Tests\Symfony\Bundle\Test; +namespace ApiPlatform\Tests\Test; -use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; -use ApiPlatform\Symfony\Bundle\Test\Response; +use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Test\Response; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy; diff --git a/tests/Symfony/Bundle/Test/Constraint/ArraySubsetTest.php b/tests/Test/Constraint/ArraySubsetTest.php similarity index 97% rename from tests/Symfony/Bundle/Test/Constraint/ArraySubsetTest.php rename to tests/Test/Constraint/ArraySubsetTest.php index f24d4e0fd5b..a7560875188 100644 --- a/tests/Symfony/Bundle/Test/Constraint/ArraySubsetTest.php +++ b/tests/Test/Constraint/ArraySubsetTest.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Tests\Symfony\Bundle\Test\Constraint; +namespace ApiPlatform\Tests\Test\Constraint; -use ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset; +use ApiPlatform\Test\Constraint\ArraySubset; use ApiPlatform\Tests\Fixtures\ArrayAccessible; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\ExpectationFailedException; diff --git a/tests/Symfony/Bundle/Test/Constraint/MatchesJsonSchemaTest.php b/tests/Test/Constraint/MatchesJsonSchemaTest.php similarity index 88% rename from tests/Symfony/Bundle/Test/Constraint/MatchesJsonSchemaTest.php rename to tests/Test/Constraint/MatchesJsonSchemaTest.php index 48cb8fe3e2e..5477301b565 100644 --- a/tests/Symfony/Bundle/Test/Constraint/MatchesJsonSchemaTest.php +++ b/tests/Test/Constraint/MatchesJsonSchemaTest.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Tests\Symfony\Bundle\Test\Constraint; +namespace ApiPlatform\Tests\Test\Constraint; -use ApiPlatform\Symfony\Bundle\Test\Constraint\MatchesJsonSchema; +use ApiPlatform\Test\Constraint\MatchesJsonSchema; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Bundle/Test/ResponseTest.php b/tests/Test/ResponseTest.php similarity index 98% rename from tests/Symfony/Bundle/Test/ResponseTest.php rename to tests/Test/ResponseTest.php index 4d5c674420f..9832d379241 100644 --- a/tests/Symfony/Bundle/Test/ResponseTest.php +++ b/tests/Test/ResponseTest.php @@ -11,9 +11,9 @@ declare(strict_types=1); -namespace ApiPlatform\Tests\Symfony\Bundle\Test; +namespace ApiPlatform\Tests\Test; -use ApiPlatform\Symfony\Bundle\Test\Response; +use ApiPlatform\Test\Response; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\BrowserKit\Response as BrowserKitResponse;