From d954c9d851585f6908525ada5fb3b83bce7ed432 Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Wed, 22 Mar 2017 15:58:35 +0100 Subject: [PATCH] Allow writing product options via API --- .../config/routing/product_option.yml | 1 - .../config/serializer/Model.ProductOption.yml | 4 + tests/Controller/ProductOptionApiTest.php | 248 ++++++++++++++++++ .../product_option/create_response.json | 54 ++++ .../create_validation_fail_response.json | 19 ++ .../product_option/index_response.json | 2 + .../index_response_after_delete.json | 33 +++ .../product_option/show_response.json | 1 + .../show_response_after_partial_update.json | 69 +++++ .../show_response_after_update.json | 69 +++++ 10 files changed, 499 insertions(+), 1 deletion(-) create mode 100644 tests/Responses/Expected/product_option/create_response.json create mode 100644 tests/Responses/Expected/product_option/create_validation_fail_response.json create mode 100644 tests/Responses/Expected/product_option/index_response_after_delete.json create mode 100644 tests/Responses/Expected/product_option/show_response_after_partial_update.json create mode 100644 tests/Responses/Expected/product_option/show_response_after_update.json diff --git a/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_option.yml b/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_option.yml index e49d8db8c86e..75d265ac3f0b 100644 --- a/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_option.yml +++ b/src/Sylius/Bundle/AdminApiBundle/Resources/config/routing/product_option.yml @@ -6,7 +6,6 @@ sylius_admin_api_product_option: identifier: code alias: sylius.product_option section: admin_api - only: ['index', 'show'] serialization_version: $version criteria: code: $code diff --git a/src/Sylius/Bundle/ProductBundle/Resources/config/serializer/Model.ProductOption.yml b/src/Sylius/Bundle/ProductBundle/Resources/config/serializer/Model.ProductOption.yml index d683e2f8c8fc..11332bb1aa39 100644 --- a/src/Sylius/Bundle/ProductBundle/Resources/config/serializer/Model.ProductOption.yml +++ b/src/Sylius/Bundle/ProductBundle/Resources/config/serializer/Model.ProductOption.yml @@ -19,6 +19,10 @@ Sylius\Component\Product\Model\ProductOption: expose: true type: array groups: [Default, Detailed] + translations: + expose: true + type: array + groups: [Default, Detailed] relations: - rel: self href: diff --git a/tests/Controller/ProductOptionApiTest.php b/tests/Controller/ProductOptionApiTest.php index 0f8d8271878a..ea70cc3d0abf 100644 --- a/tests/Controller/ProductOptionApiTest.php +++ b/tests/Controller/ProductOptionApiTest.php @@ -20,6 +20,14 @@ */ final class ProductOptionApiTest extends JsonApiTestCase { + /** + * @var array + */ + private static $authorizedHeaderWithContentType = [ + 'HTTP_Authorization' => 'Bearer SampleTokenNjZkNjY2MDEwMTAzMDkxMGE0OTlhYzU3NzYyMTE0ZGQ3ODcyMDAwM2EwMDZjNDI5NDlhMDdlMQ', + 'CONTENT_TYPE' => 'application/json', + ]; + /** * @var array */ @@ -84,6 +92,246 @@ public function it_allows_showing_product_option() $this->assertResponse($response, 'product_option/show_response', Response::HTTP_OK); } + /** + * @test + */ + public function it_does_not_allow_delete_product_option_if_it_does_not_exist() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + + $this->client->request('DELETE', '/api/v1/product-options/-1', [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + + $this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND); + } + + /** + * @test + */ + public function it_allows_delete_product_option() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $productOptions = $this->loadFixturesFromFile('resources/product_options.yml'); + $productOption = $productOptions['mug-size']; + + $this->client->request('DELETE', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithContentType, []); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', '/api/v1/product-options/', [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_option/index_response_after_delete', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_allows_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); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_option/create_response', Response::HTTP_CREATED); + } + + /** + * @test + */ + public function it_does_not_allow_to_create_product_option_without_required_fields() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + + $this->client->request('POST', '/api/v1/product-options/', [], [], static::$authorizedHeaderWithContentType, []); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_option/create_validation_fail_response', Response::HTTP_BAD_REQUEST); + } + + /** + * @test + */ + public function it_allows_to_update_product_option_with_multiple_translations() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $this->loadFixturesFromFile('resources/locales.yml'); + $productOptions = $this->loadFixturesFromFile('resources/product_options.yml'); + $productOption = $productOptions['mug-size']; + + $data = <<client->request('PUT', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithContentType, $data); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_option/show_response_after_update', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_allows_to_partially_update_product_option_with_multiple_translations() + { + $this->loadFixturesFromFile('authentication/api_administrator.yml'); + $this->loadFixturesFromFile('resources/locales.yml'); + $productOptions = $this->loadFixturesFromFile('resources/product_options.yml'); + $productOption = $productOptions['mug-size']; + + $data = <<client->request('PATCH', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithContentType, $data); + + $response = $this->client->getResponse(); + $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); + + $this->client->request('GET', $this->getProductOptionUrl($productOption), [], [], static::$authorizedHeaderWithAccept); + + $response = $this->client->getResponse(); + $this->assertResponse($response, 'product_option/show_response_after_partial_update', Response::HTTP_OK); + } + /** * @param ProductOptionInterface $productOption * diff --git a/tests/Responses/Expected/product_option/create_response.json b/tests/Responses/Expected/product_option/create_response.json new file mode 100644 index 000000000000..5a3827f9d56b --- /dev/null +++ b/tests/Responses/Expected/product_option/create_response.json @@ -0,0 +1,54 @@ +{ + "id": @integer@, + "code": "MUG_SIZE", + "position": 0, + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug size" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "name": "Bechergröße" + } + }, + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Small" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Klein" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Groß" + }, + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Large" + } + } + } + ], + "_links": { + "self": { + "href": "\/api\/v1\/products\/MUG_SIZE" + } + } +} diff --git a/tests/Responses/Expected/product_option/create_validation_fail_response.json b/tests/Responses/Expected/product_option/create_validation_fail_response.json new file mode 100644 index 000000000000..c937c78207e5 --- /dev/null +++ b/tests/Responses/Expected/product_option/create_validation_fail_response.json @@ -0,0 +1,19 @@ +{ + "code": 400, + "message": "Validation Failed", + "errors": { + "errors": [ + "Please add at least 2 option values." + ], + "children": { + "position": {}, + "translations": {}, + "values": {}, + "code": { + "errors": [ + "Please enter option code." + ] + } + } + } +} diff --git a/tests/Responses/Expected/product_option/index_response.json b/tests/Responses/Expected/product_option/index_response.json index daf090d0a74f..30915fd7f406 100644 --- a/tests/Responses/Expected/product_option/index_response.json +++ b/tests/Responses/Expected/product_option/index_response.json @@ -20,6 +20,7 @@ "id": @integer@, "code": "MUG_SIZE", "position": 0, + "translations": {}, "values": [ { "code": "MUG_SIZE_S", @@ -52,6 +53,7 @@ "id": @integer@, "code": "MUG_COLOR", "position": 1, + "translations": {}, "values": [], "_links": { "self": { diff --git a/tests/Responses/Expected/product_option/index_response_after_delete.json b/tests/Responses/Expected/product_option/index_response_after_delete.json new file mode 100644 index 000000000000..f5eacd9c0f21 --- /dev/null +++ b/tests/Responses/Expected/product_option/index_response_after_delete.json @@ -0,0 +1,33 @@ +{ + "page": 1, + "limit": 10, + "pages": 1, + "total": 1, + "_links": { + "self": { + "href": "\/api\/v1\/product-options\/?page=1&limit=10" + }, + "first": { + "href": "\/api\/v1\/product-options\/?page=1&limit=10" + }, + "last": { + "href": "\/api\/v1\/product-options\/?page=1&limit=10" + } + }, + "_embedded": { + "items": [ + { + "id": @integer@, + "code": "MUG_COLOR", + "position": 0, + "translations": {}, + "values": [], + "_links": { + "self": { + "href": "\/api\/v1\/products\/MUG_COLOR" + } + } + } + ] + } +} diff --git a/tests/Responses/Expected/product_option/show_response.json b/tests/Responses/Expected/product_option/show_response.json index 8c5ffd804faa..034ea9d77dd1 100644 --- a/tests/Responses/Expected/product_option/show_response.json +++ b/tests/Responses/Expected/product_option/show_response.json @@ -2,6 +2,7 @@ "id": @integer@, "code": "MUG_SIZE", "position": 0, + "translations": {}, "values": [ { "code": "MUG_SIZE_S", diff --git a/tests/Responses/Expected/product_option/show_response_after_partial_update.json b/tests/Responses/Expected/product_option/show_response_after_partial_update.json new file mode 100644 index 000000000000..54169d5b72dd --- /dev/null +++ b/tests/Responses/Expected/product_option/show_response_after_partial_update.json @@ -0,0 +1,69 @@ +{ + "id": @integer@, + "code": "MUG_SIZE", + "position": 0, + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug size" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "name": "Bechergröße" + } + }, + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Small" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Klein" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Large" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Groß" + } + } + }, + { + "code": "MUG_SIZE_M", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Medium" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Mittel" + } + } + } + ], + "_links": { + "self": { + "href": "\/api\/v1\/products\/MUG_SIZE" + } + } +} diff --git a/tests/Responses/Expected/product_option/show_response_after_update.json b/tests/Responses/Expected/product_option/show_response_after_update.json new file mode 100644 index 000000000000..e043c11828ac --- /dev/null +++ b/tests/Responses/Expected/product_option/show_response_after_update.json @@ -0,0 +1,69 @@ +{ + "id": @integer@, + "code": "MUG_SIZE", + "position": 1, + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "name": "Mug size" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "name": "Bechergröße" + } + }, + "values": [ + { + "code": "MUG_SIZE_S", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Small" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Klein" + } + } + }, + { + "code": "MUG_SIZE_L", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Large" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Groß" + } + } + }, + { + "code": "MUG_SIZE_M", + "translations": { + "en_US": { + "id": @integer@, + "locale": "en_US", + "value": "Medium" + }, + "de_CH": { + "id": @integer@, + "locale": "de_CH", + "value": "Mittel" + } + } + } + ], + "_links": { + "self": { + "href": "\/api\/v1\/products\/MUG_SIZE" + } + } +}