diff --git a/docs/api/product_attributes.rst b/docs/api/product_attributes.rst index e90283ec0a1..69af417bb69 100644 --- a/docs/api/product_attributes.rst +++ b/docs/api/product_attributes.rst @@ -48,6 +48,181 @@ If you request for more detailed data, you will receive an object with the follo Read more about :doc:`Product Attributes in the component docs`. +Creating a Product Attribute +---------------------------- + +To create a new product attribute you will need to call the ``/api/v1/products-attributes/{type}`` endpoint with the ``POST`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + POST /api/v1/product-attributes/{type} + ++---------------+----------------+--------------------------------------------------+ +| Parameter | Parameter type | Description | ++===============+================+==================================================+ +| Authorization | header | Token received during authentication | ++---------------+----------------+--------------------------------------------------+ +| type | url attribute | Type of the product attribute (for example text) | ++---------------+----------------+--------------------------------------------------+ +| code | request | **(unique)** Product attribute identifier | ++---------------+----------------+--------------------------------------------------+ + +Example +^^^^^^^ + +To create a new text product attribute use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-attributes/text \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X POST \ + --data ' + { + "code": "mug_material" + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 201 CREATED + +.. code-block:: json + + { + "id": 1, + "code": "mug_material", + "type": "text", + "values": [], + "position": 0, + "translations": {}, + "values": [], + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/mug_material" + } + } + } + +.. warning:: + + If you try to create a product attribute without code you will receive a ``400 Bad Request`` error, that will contain validation errors. + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-attributes/text \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X POST \ + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 400 BAD REQUEST + +.. code-block:: json + + { + "code": 400, + "message": "Validation Failed", + "errors": { + "children": { + "type": {}, + "position": {}, + "translations": {}, + "code": { + "errors": [ + "Please enter attribute code." + ] + }, + "configuration": { + "children": { + "min": {}, + "max": {} + } + } + } + } + } + +You can also create a product attribute with additional (not required) fields: + ++------------------------------------+----------------+----------------------------------------------------------------------------+ +| Parameter | Parameter type | Description | ++====================================+================+============================================================================+ +| position | request | Position within sorted product attribute list of the new product attribute | ++------------------------------------+----------------+----------------------------------------------------------------------------+ +| translations['localeCode']['name'] | request | Name of the product attribute | ++------------------------------------+----------------+----------------------------------------------------------------------------+ + +Example +^^^^^^^ + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-attributes/text/ \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X POST \ + --data ' + { + "code": "mug_material", + "translations": { + "de_CH": { + "name": "Becher Material" + }, + "en_US": { + "name": "Mug material" + } + } + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 201 CREATED + +.. code-block:: json + + { + "id": 1, + "code": "mug_material", + "type": "text", + "values": [], + "position": 0, + "createdAt": "2017-02-24T16:14:05+0100", + "updatedAt": "2017-02-24T16:14:05+0100", + "translations": { + "de_CH": { + "id": 1, + "locale": "de_CH", + "name": "Becher Material" + }, + "en_US": { + "id": 2, + "locale": "en_US", + "name": "Mug material" + } + }, + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/mug_material" + } + } + } + Getting a Single Product Attribute ---------------------------------- @@ -463,3 +638,135 @@ Exemplary Response ] } } + +Updating a Product Attribute +---------------------------- + +To fully update a product attribute you will need to call the ``/api/v1/product-attributes/code`` endpoint with the ``PUT`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + PUT /api/v1/product-attributes/{code} + ++-----------------------------------+----------------+--------------------------------------+ +| Parameter | Parameter type | Description | ++===================================+================+======================================+ +| Authorization | header | Token received during authentication | ++-----------------------------------+----------------+--------------------------------------+ +| code | url attribute | Unique product attribute identifier | ++-----------------------------------+----------------+--------------------------------------+ + +Example +^^^^^^^ + + To fully update the product attribute with ``code = mug_material`` use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-attributes/mug_material \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X PUT \ + --data ' + { + "translations": { + "en_US": { + "name": "Mug material" + } + } + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 204 No Content + +To update a product attribute partially you will need to call the ``/api/v1/product-attributes/code`` endpoint with the ``PATCH`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + PATCH /api/v1/product-attributes/{code} + ++---------------+----------------+--------------------------------------+ +| Parameter | Parameter type | Description | ++===============+================+======================================+ +| Authorization | header | Token received during authentication | ++---------------+----------------+--------------------------------------+ +| code | url attribute | Unique product attribute identifier | ++---------------+----------------+--------------------------------------+ + +Example +^^^^^^^ + +To partially update the product attribute with ``code = mug_material`` use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-attributes/mug_material \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X PATCH \ + --data ' + { + "translations": { + "en_US": { + "name": "Mug material" + } + } + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 204 No Content + +Deleting a Product Attribute +---------------------------- + +To delete a product attribute you will need to call the ``/api/v1/product-attributes/code`` endpoint with the ``DELETE`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + DELETE /api/v1/product-attributes/{code} + ++---------------+----------------+--------------------------------------+ +| Parameter | Parameter type | Description | ++===============+================+======================================+ +| Authorization | header | Token received during authentication | ++---------------+----------------+--------------------------------------+ +| code | url attribute | Unique product attribute identifier | ++---------------+----------------+--------------------------------------+ + +Example +^^^^^^^ + +To delete the product attribute with ``code = mug_material`` use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-attributes/mug_material \ + -H "Authorization: Bearer SampleToken" \ + -H "Accept: application/json" \ + -X DELETE + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 204 No Content diff --git a/docs/api/product_options.rst b/docs/api/product_options.rst index a0adf747ca6..a36fdac156e 100644 --- a/docs/api/product_options.rst +++ b/docs/api/product_options.rst @@ -20,23 +20,299 @@ If you request a product option via API, you will receive an object with the fol If you request for more detailed data, you will receive an object with the following fields: -+----------+----------------------------------------------------------------+ -| Field | Description | -+==========+================================================================+ -| id | Id of the product option | -+----------+----------------------------------------------------------------+ -| code | Unique product option identifier | -+----------+----------------------------------------------------------------+ -| position | The position of the product option among other product options | -+----------+----------------------------------------------------------------+ -| values | Names of options in which the product can occur | -+----------+----------------------------------------------------------------+ ++--------------+-------------------------------------------------------------------+ +| Field | Description | ++==============+===================================================================+ +| id | Id of the product option | ++--------------+-------------------------------------------------------------------+ +| code | Unique product option identifier | ++--------------+-------------------------------------------------------------------+ +| position | The position of the product option among other product options | ++--------------+-------------------------------------------------------------------+ +| translations | Collection of translations (each contains name in given language) | ++--------------+-------------------------------------------------------------------+ +| values | Names of options in which the product can occur | ++--------------+-------------------------------------------------------------------+ .. note:: Read more about :doc:`Product Options in the component docs`. +Creating a Product Option +------------------------- + +To create a new product option you will need to call the ``/api/v1/products-options/`` endpoint with the ``POST`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + POST /api/v1/product-options/ + ++-----------------------------------+----------------+----------------------------------------+ +| Parameter | Parameter type | Description | ++===================================+================+========================================+ +| Authorization | header | Token received during authentication | ++-----------------------------------+----------------+----------------------------------------+ +| code | request | **(unique)** Product option identifier | ++-----------------------------------+----------------+----------------------------------------+ +| values | request | At least two option values | ++-----------------------------------+----------------+----------------------------------------+ + +Example +^^^^^^^ + +To create a new product option use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-options/ \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X POST \ + --data ' + { + "code": "MUG_SIZE", + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "en_US": { + "value": "Small" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "en_US": { + "value": "Large" + } + } + } + ] + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 201 CREATED + +.. code-block:: json + + { + "id": 1, + "code": "MUG_SIZE", + "position": 0, + "translations": {}, + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "en_US": { + "id": 1, + "locale": "en_US", + "value": "Small" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "en_US": { + "id": 2, + "locale": "en_US", + "value": "Large" + } + } + } + ], + "_links": { + "self": { + "href": "\/api\/v1\/product-options\/MUG_SIZE" + } + } + } + +.. warning:: + + If you try to create a product option without all necessary fields you will receive a ``400 Bad Request`` error, that will contain validation errors. + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-options/ \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X POST \ + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 400 BAD REQUEST + +.. code-block:: json + + { + "code": 400, + "message": "Validation Failed", + "errors": { + "errors": [ + "Please add at least 2 option values." + ], + "children": { + "position": {}, + "translations": {}, + "values": {}, + "code": { + "errors": [ + "Please enter option code." + ] + } + } + } + } + + +You can also create a product option with additional (not required) fields: + ++------------------------------------+----------------+----------------------------------------------------------------------+ +| Parameter | Parameter type | Description | ++====================================+================+======================================================================+ +| position | request | Position within sorted product option list of the new product option | ++------------------------------------+----------------+----------------------------------------------------------------------+ +| translations['localeCode']['name'] | request | Name of the product option | ++------------------------------------+----------------+----------------------------------------------------------------------+ +| values | request | Collection of option values | ++------------------------------------+----------------+----------------------------------------------------------------------+ + +Each product option value has the following fields: + ++-------------------------------------+----------------+----------------------------------------------+ +| Parameter | Parameter type | Description | ++=====================================+================+==============================================+ +| code | request | **(unique)** Product option value identifier | ++-------------------------------------+----------------+----------------------------------------------+ +| translations['localeCode']['value'] | request | Translation of the value | ++-------------------------------------+----------------+----------------------------------------------+ + +Example +^^^^^^^ + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-options/ \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X POST \ + --data ' + { + "code": "MUG_SIZE", + "translations": { + "de_CH": { + "name": "Bechergröße" + }, + "en_US": { + "name": "Mug size" + } + }, + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "de_CH": { + "value": "Klein" + }, + "en_US": { + "value": "Small" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "de_CH": { + "value": "Groß" + }, + "en_US": { + "value": "Large" + } + } + } + ] + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 201 CREATED + +.. code-block:: json + + { + "id": 1, + "code": "MUG_SIZE", + "position": 0, + "translations": { + "en_US": { + "id": 1, + "locale": "en_US", + "name": "Mug size" + }, + "de_CH": { + "id": 2, + "locale": "de_CH", + "name": "Bechergröße" + } + }, + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "en_US": { + "id": 1, + "locale": "en_US", + "value": "Small" + }, + "de_CH": { + "id": 2, + "locale": "de_CH", + "value": "Klein" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "de_CH": { + "id": 3, + "locale": "de_CH", + "value": "Groß" + }, + "en_US": { + "id": 4, + "locale": "en_US", + "value": "Large" + } + } + } + ], + "_links": { + "self": { + "href": "\/api\/v1\/products\/MUG_SIZE" + } + } + } + Getting a Single Product Option ------------------------------- @@ -60,11 +336,11 @@ Definition Example ^^^^^^^ -To see the details of the product option with ``code = mug_type`` use the below method: +To see the details of the product option with ``code = MUG_TYPE`` use the below method: .. code-block:: bash - $ curl http://demo.sylius.org/api/v1/product-options/mug_type \ + $ curl http://demo.sylius.org/api/v1/product-options/MUG_TYPE \ -H "Authorization: Bearer SampleToken" \ -H "Accept: application/json" @@ -83,8 +359,15 @@ Exemplary Response { "id": 1, - "code": "mug_type", + "code": "MUG_TYPE", "position": 0, + "translations": { + "en_US": { + "locale": "en_US", + "id": 1, + "value": "Mug type" + } + }, "values": [ { "code": "mug_type_medium", @@ -119,7 +402,7 @@ Exemplary Response ], "_links": { "self": { - "href": "\/api\/v1\/products\/mug_type" + "href": "\/api\/v1\/products\/MUG_TYPE" } } } @@ -188,6 +471,13 @@ Exemplary Response "id": 1, "code": "mug_type", "position": 0, + "translations": { + "en_US": { + "locale": "en_US", + "id": 1, + "value": "Mug type" + } + }, "values": [ { "code": "mug_type_medium", @@ -230,6 +520,13 @@ Exemplary Response "id": 2, "code": "sticker_size", "position": 1, + "translations": { + "en_US": { + "locale": "en_US", + "id": 2, + "value": "Sticker size" + } + }, "values": [ { "code": "sticker_size-3", @@ -272,6 +569,13 @@ Exemplary Response "id": 3, "code": "t_shirt_color", "position": 2, + "translations": { + "en_US": { + "locale": "en_US", + "id": 3, + "value": "T-Shirt color" + } + }, "values": [ { "code": "t_shirt_color_red", @@ -314,6 +618,13 @@ Exemplary Response "id": 4, "code": "t_shirt_size", "position": 3, + "translations": { + "en_US": { + "locale": "en_US", + "id": 4, + "value": "T-Shirt size" + } + }, "values": [ { "code": "t_shirt_size_s", @@ -375,3 +686,135 @@ Exemplary Response ] } } + +Updating a Product Option +------------------------- + +To fully update a product option you will need to call the ``/api/v1/product-options/code`` endpoint with the ``PUT`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + PUT /api/v1/product-options/{code} + ++-----------------------------------+----------------+--------------------------------------+ +| Parameter | Parameter type | Description | ++===================================+================+======================================+ +| Authorization | header | Token received during authentication | ++-----------------------------------+----------------+--------------------------------------+ +| code | url attribute | Unique product option identifier | ++-----------------------------------+----------------+--------------------------------------+ + +Example +^^^^^^^ + + To fully update the product option with ``code = MUG_SIZE`` use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-options/MUG_SIZE \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X PUT \ + --data ' + { + "translations": { + "en_US": { + "name": "Mug size" + } + } + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 204 No Content + +To update a product option partially you will need to call the ``/api/v1/product-options/code`` endpoint with the ``PATCH`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + PATCH /api/v1/product-options/{code} + ++---------------+----------------+--------------------------------------+ +| Parameter | Parameter type | Description | ++===============+================+======================================+ +| Authorization | header | Token received during authentication | ++---------------+----------------+--------------------------------------+ +| code | url attribute | Unique product option identifier | ++---------------+----------------+--------------------------------------+ + +Example +^^^^^^^ + +To partially update the product option with ``code = MUG_SIZE`` use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-options/MUG_SIZE \ + -H "Authorization: Bearer SampleToken" \ + -H "Content-Type: application/json" \ + -X PATCH \ + --data ' + { + "translations": { + "en_US": { + "name": "Mug size" + } + } + } + ' + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 204 No Content + +Deleting a Product Option +------------------------- + +To delete a product option you will need to call the ``/api/v1/product-options/code`` endpoint with the ``DELETE`` method. + +Definition +^^^^^^^^^^ + +.. code-block:: text + + DELETE /api/v1/product-options/{code} + ++---------------+----------------+--------------------------------------+ +| Parameter | Parameter type | Description | ++===============+================+======================================+ +| Authorization | header | Token received during authentication | ++---------------+----------------+--------------------------------------+ +| code | url attribute | Unique product option identifier | ++---------------+----------------+--------------------------------------+ + +Example +^^^^^^^ + +To delete the product option with ``code = MUG_SIZE`` use the below method: + +.. code-block:: bash + + $ curl http://demo.sylius.org/api/v1/product-options/MUG_SIZE \ + -H "Authorization: Bearer SampleToken" \ + -H "Accept: application/json" \ + -X DELETE + +Exemplary Response +^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + STATUS: 204 No Content diff --git a/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_attribute.yml b/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_attribute.yml index a6930f6c4a7..82a469505f5 100644 --- a/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_attribute.yml +++ b/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_attribute.yml @@ -6,8 +6,20 @@ sylius_admin_api_product_attribute: identifier: code alias: sylius.product_attribute section: admin_api - only: ['index', 'show'] + except: ['create'] serialization_version: $version criteria: code: $code type: sylius.resource_api + +sylius_admin_api_product_attribute_create: + path: /product-attributes/{type} + methods: [POST] + defaults: + _controller: sylius.controller.product_attribute:createAction + _sylius: + serialization_version: $version + factory: + method: createTyped + arguments: + type: $type diff --git a/tests/Controller/ProductAttributeApiTest.php b/tests/Controller/ProductAttributeApiTest.php index 7eab70ebd15..30f2c413f07 100644 --- a/tests/Controller/ProductAttributeApiTest.php +++ b/tests/Controller/ProductAttributeApiTest.php @@ -20,6 +20,14 @@ */ final class ProductAttributeApiTest extends JsonApiTestCase { + /** + * @var array + */ + private static $authorizedHeaderWithContentType = [ + 'HTTP_Authorization' => 'Bearer SampleTokenNjZkNjY2MDEwMTAzMDkxMGE0OTlhYzU3NzYyMTE0ZGQ3ODcyMDAwM2EwMDZjNDI5NDlhMDdlMQ', + 'CONTENT_TYPE' => 'application/json', + ]; + /** * @var array */ @@ -84,6 +92,193 @@ public function it_allows_showing_product_attribute() $this->assertResponse($response, 'product_attribute/show_response', Response::HTTP_OK); } + /** + * @test + */ + public function it_does_not_allow_to_delete_product_attribute_if_it_does_not_exist() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + + $this->client->request('DELETE', '/api/v1/product-attributes/-1', [], [], static::$authorizedHeaderWithContentType); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND); + } + + /** + * @test + */ + public function it_allows_to_delete_product_attribute() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml'); + $productAttribute = $productAttributes['productAttribute1']; + + $this->client->request('DELETE', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', '/api/v1/product-attributes/', [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_attribute/index_response_after_delete', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_allows_to_create_product_attribute() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $this->loadFixturesFromFile('resources/locales.yml'); + + $data = +<<client->request('POST', '/api/v1/product-attributes/text', [], [], static::$authorizedHeaderWithContentType, $data); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_attribute/create_response', Response::HTTP_CREATED); + } + + /** + * @test + */ + public function it_does_not_allow_to_create_product_attribute_without_required_fields() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + + $this->client->request('POST', '/api/v1/product-attributes/text', [], [], static::$authorizedHeaderWithContentType, []); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_attribute/create_validation_fail_response', Response::HTTP_BAD_REQUEST); + } + + /** + * @test + */ + public function it_does_not_allow_to_create_product_attribute_without_type() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + + $this->client->request('POST', '/api/v1/product-attributes', [], [], static::$authorizedHeaderWithContentType, []); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_METHOD_NOT_ALLOWED); + } + + /** + * @test + */ + public function it_allows_to_update_product_attribute() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $this->loadFixturesFromFile('resources/locales.yml'); + $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml'); + $productAttribute = $productAttributes['productAttribute1']; + + $data = +<<client->request('PUT', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType, $data); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_attribute/show_response_after_update', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_allows_to_partially_update_product_attribute() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $this->loadFixturesFromFile('resources/locales.yml'); + $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml'); + $productAttribute = $productAttributes['productAttribute1']; + + $data = +<<client->request('PATCH', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType, $data); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_attribute/show_response_after_partial_update', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_does_not_allow_to_change_product_attribute_type() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $this->loadFixturesFromFile('resources/locales.yml'); + $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml'); + $productAttribute = $productAttributes['productAttribute1']; + + $data = +<<client->request('PATCH', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType, $data); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_attribute/show_response', Response::HTTP_OK); + } + /** * @param ProductAttributeInterface $productAttribute * diff --git a/tests/Controller/ProductOptionApiTest.php b/tests/Controller/ProductOptionApiTest.php index 079f04019dd..56aa59591b5 100644 --- a/tests/Controller/ProductOptionApiTest.php +++ b/tests/Controller/ProductOptionApiTest.php @@ -134,42 +134,43 @@ public function it_allows_to_create_product_option_with_multiple_translations() $this->loadFixturesFromFile('authentication/api_administrator.yml'); $this->loadFixturesFromFile('resources/locales.yml'); - $data = <<client->request('POST', '/api/v1/product-options/', [], [], static::$authorizedHeaderWithContentType, $data); @@ -201,54 +202,55 @@ public function it_allows_to_update_product_option_with_multiple_translations() $productOptions = $this->loadFixturesFromFile('resources/product_options.yml'); $productOption = $productOptions['mug-size']; - $data = <<client->request('PUT', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithContentType, $data); @@ -272,53 +274,54 @@ public function it_allows_to_partially_update_product_option_with_multiple_trans $productOptions = $this->loadFixturesFromFile('resources/product_options.yml'); $productOption = $productOptions['mug-size']; - $data = <<client->request('PATCH', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithContentType, $data); diff --git a/tests/Responses/Expected/product_attribute/create_response.json b/tests/Responses/Expected/product_attribute/create_response.json new file mode 100644 index 00000000000..48a4866658e --- /dev/null +++ b/tests/Responses/Expected/product_attribute/create_response.json @@ -0,0 +1,26 @@ +{ + "id": @integer@, + "code": "mug_material", + "type": "text", + "values": [], + "position": 0, + "createdAt": "@string@.isDateTime()", + "updatedAt": "@string@.isDateTime()", + "translations": { + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "name": "Becher Material" + }, + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug material" + } + }, + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/mug_material" + } + } +} diff --git a/tests/Responses/Expected/product_attribute/create_validation_fail_response.json b/tests/Responses/Expected/product_attribute/create_validation_fail_response.json new file mode 100644 index 00000000000..da43bb2cf34 --- /dev/null +++ b/tests/Responses/Expected/product_attribute/create_validation_fail_response.json @@ -0,0 +1,22 @@ +{ + "code": 400, + "message": "Validation Failed", + "errors": { + "children": { + "type": {}, + "position": {}, + "translations": {}, + "code": { + "errors": [ + "Please enter attribute code." + ] + }, + "configuration": { + "children": { + "min": {}, + "max": {} + } + } + } + } +} diff --git a/tests/Responses/Expected/product_attribute/index_response_after_delete.json b/tests/Responses/Expected/product_attribute/index_response_after_delete.json new file mode 100644 index 00000000000..ac13b0e9616 --- /dev/null +++ b/tests/Responses/Expected/product_attribute/index_response_after_delete.json @@ -0,0 +1,44 @@ +{ + "page": 1, + "limit": 10, + "pages": 1, + "total": 1, + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/?page=1&limit=10" + }, + "first": { + "href": "\/api\/v1\/product-attributes\/?page=1&limit=10" + }, + "last": { + "href": "\/api\/v1\/product-attributes\/?page=1&limit=10" + } + }, + "_embedded": { + "items": [ + { + "id": @integer@, + "code": "mug_collection", + "type": "text", + "position": 0, + "translations": { + "de": { + "id": @integer@, + "locale": "de", + "name": "Becher Material" + }, + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug material" + } + }, + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/mug_collection" + } + } + } + ] + } +} diff --git a/tests/Responses/Expected/product_attribute/show_response_after_partial_update.json b/tests/Responses/Expected/product_attribute/show_response_after_partial_update.json new file mode 100644 index 00000000000..c779222e5d4 --- /dev/null +++ b/tests/Responses/Expected/product_attribute/show_response_after_partial_update.json @@ -0,0 +1,31 @@ +{ + "id": @integer@, + "code": "mug_material", + "type": "text", + "values": [], + "position": 0, + "createdAt": "@string@.isDateTime()", + "updatedAt": "@string@.isDateTime()", + "translations": { + "de": { + "id": @integer@, + "locale": "de", + "name": "Becher Sammlung" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "name": "Becher Material" + }, + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug material" + } + }, + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/mug_material" + } + } +} diff --git a/tests/Responses/Expected/product_attribute/show_response_after_update.json b/tests/Responses/Expected/product_attribute/show_response_after_update.json new file mode 100644 index 00000000000..5ad9c89d037 --- /dev/null +++ b/tests/Responses/Expected/product_attribute/show_response_after_update.json @@ -0,0 +1,31 @@ +{ + "id": @integer@, + "code": "mug_material", + "type": "text", + "values": [], + "position": 1, + "createdAt": "@string@.isDateTime()", + "updatedAt": "@string@.isDateTime()", + "translations": { + "de": { + "id": @integer@, + "locale": "de", + "name": "Becher Sammlung" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "name": "Becher Material" + }, + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug material" + } + }, + "_links": { + "self": { + "href": "\/api\/v1\/product-attributes\/mug_material" + } + } +}