Completed
Push — master ( 9a4fa3...1bdebc )
by Kamil
41s queued 22s
created

it_allows_indexing_product_attributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Tests\Controller;
15
16
use Lakion\ApiTestCase\JsonApiTestCase;
17
use PHPUnit\Framework\Assert;
18
use Sylius\Component\Product\Model\ProductAttributeInterface;
19
use Symfony\Component\HttpFoundation\Response;
20
21
/**
22
 * @author Anna Walasek <[email protected]>
23
 */
24
final class ProductAttributeApiTest extends JsonApiTestCase
25
{
26
    /**
27
     * @var array
28
     */
29
    private static $authorizedHeaderWithContentType = [
30
        'HTTP_Authorization' => 'Bearer SampleTokenNjZkNjY2MDEwMTAzMDkxMGE0OTlhYzU3NzYyMTE0ZGQ3ODcyMDAwM2EwMDZjNDI5NDlhMDdlMQ',
31
        'CONTENT_TYPE' => 'application/json',
32
    ];
33
34
    /**
35
     * @var array
36
     */
37
    private static $authorizedHeaderWithAccept = [
38
        'HTTP_Authorization' => 'Bearer SampleTokenNjZkNjY2MDEwMTAzMDkxMGE0OTlhYzU3NzYyMTE0ZGQ3ODcyMDAwM2EwMDZjNDI5NDlhMDdlMQ',
39
        'ACCEPT' => 'application/json',
40
    ];
41
42
    /**
43
     * @test
44
     */
45
    public function it_does_not_allow_to_show_product_attributes_list_when_access_is_denied()
46
    {
47
        $this->loadFixturesFromFile('resources/product_attributes.yml');
48
49
        $this->client->request('GET', '/api/v1/product-attributes/');
50
51
        $response = $this->client->getResponse();
52
        $this->assertResponse($response, 'authentication/access_denied_response', Response::HTTP_UNAUTHORIZED);
53
    }
54
55
    /**
56
     * @test
57
     */
58
    public function it_allows_indexing_product_attributes()
59
    {
60
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
61
        $this->loadFixturesFromFile('resources/product_attributes.yml');
62
63
        $this->client->request('GET', '/api/v1/product-attributes/', [], [], static::$authorizedHeaderWithAccept);
64
65
        $response = $this->client->getResponse();
66
        $this->assertResponse($response, 'product_attribute/index_response', Response::HTTP_OK);
67
    }
68
69
    /**
70
     * @test
71
     */
72
    public function it_does_not_allow_to_show_product_attribute_when_it_does_not_exist()
73
    {
74
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
75
76
        $this->client->request('GET', '/api/v1/product-attributes/-1', [], [], static::$authorizedHeaderWithAccept);
77
78
        $response = $this->client->getResponse();
79
        $this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND);
80
    }
81
82
    /**
83
     * @test
84
     */
85
    public function it_allows_showing_product_attribute()
86
    {
87
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
88
        $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml');
89
        $productAttribute = $productAttributes['productAttribute1'];
90
91
        $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept);
92
93
        $response = $this->client->getResponse();
94
        $this->assertResponse($response, 'product_attribute/show_response', Response::HTTP_OK);
95
    }
96
97
    /**
98
     * @test
99
     */
100
    public function it_does_not_allow_to_delete_product_attribute_if_it_does_not_exist()
101
    {
102
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
103
104
        $this->client->request('DELETE', '/api/v1/product-attributes/-1', [], [], static::$authorizedHeaderWithContentType);
105
106
        $response = $this->client->getResponse();
107
        $this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND);
108
    }
109
110
    /**
111
     * @test
112
     */
113
    public function it_allows_to_delete_product_attribute()
114
    {
115
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
116
        $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml');
117
        $productAttribute = $productAttributes['productAttribute1'];
118
119
        $this->client->request('DELETE', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType);
120
121
        $response = $this->client->getResponse();
122
        $this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
123
124
        $this->client->request('GET', '/api/v1/product-attributes/', [], [], static::$authorizedHeaderWithAccept);
125
126
        $response = $this->client->getResponse();
127
        $this->assertResponse($response, 'product_attribute/index_response_after_delete', Response::HTTP_OK);
128
    }
129
130
    /**
131
     * @test
132
     */
133
    public function it_allows_to_create_product_attribute()
134
    {
135
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
136
        $this->loadFixturesFromFile('resources/locales.yml');
137
138
        $data =
139
<<<EOT
140
        {
141
            "code": "mug_material",
142
            "translations": {
143
                "de_CH": {
144
                    "name": "Becher Material"
145
                },
146
                "en_US": {
147
                    "name": "Mug material"
148
                }
149
            }
150
        }
151
EOT;
152
153
        $this->client->request('POST', '/api/v1/product-attributes/text', [], [], static::$authorizedHeaderWithContentType, $data);
154
155
        $response = $this->client->getResponse();
156
        $this->assertResponse($response, 'product_attribute/create_response', Response::HTTP_CREATED);
157
    }
158
159
    /**
160
     * @test
161
     */
162
    public function it_does_not_allow_to_create_product_attribute_without_required_fields()
163
    {
164
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
165
166
        $this->client->request('POST', '/api/v1/product-attributes/text', [], [], static::$authorizedHeaderWithContentType, []);
167
168
        $response = $this->client->getResponse();
169
        $this->assertResponse($response, 'product_attribute/create_validation_fail_response', Response::HTTP_BAD_REQUEST);
170
    }
171
172
    /**
173
     * @test
174
     */
175
    public function it_does_not_allow_to_create_product_attribute_without_type()
176
    {
177
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
178
179
        $this->client->request('POST', '/api/v1/product-attributes', [], [], static::$authorizedHeaderWithContentType, []);
180
181
        $response = $this->client->getResponse();
182
        $this->assertResponseCode($response, Response::HTTP_METHOD_NOT_ALLOWED);
183
    }
184
185
    /**
186
     * @test
187
     */
188
    public function it_allows_to_update_product_attribute()
189
    {
190
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
191
        $this->loadFixturesFromFile('resources/locales.yml');
192
        $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml');
193
        $productAttribute = $productAttributes['productAttribute1'];
194
195
        $data =
196
<<<EOT
197
        {
198
            "position": 2,
199
            "translations": {
200
                "de_CH": {
201
                    "name": "Becher Material"
202
                },
203
                "en_US": {
204
                    "name": "Mug material"
205
                }
206
            }
207
        }
208
EOT;
209
210
        $this->client->request('PUT', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType, $data);
211
212
        $response = $this->client->getResponse();
213
        $this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
214
215
        $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept);
216
217
        $response = $this->client->getResponse();
218
        $this->assertResponse($response, 'product_attribute/show_response_after_update', Response::HTTP_OK);
219
    }
220
221
    /**
222
     * @test
223
     */
224
    public function it_allows_to_partially_update_product_attribute()
225
    {
226
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
227
        $this->loadFixturesFromFile('resources/locales.yml');
228
        $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml');
229
        $productAttribute = $productAttributes['productAttribute1'];
230
231
        $data =
232
<<<EOT
233
        {
234
            "translations": {
235
                "de_CH": {
236
                    "name": "Becher Material"
237
                },
238
                "en_US": {
239
                    "name": "Mug material"
240
                }
241
            }
242
        }
243
EOT;
244
245
        $this->client->request('PATCH', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType, $data);
246
247
        $response = $this->client->getResponse();
248
        $this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
249
250
        $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept);
251
252
        $response = $this->client->getResponse();
253
        $this->assertResponse($response, 'product_attribute/show_response_after_partial_update', Response::HTTP_OK);
254
    }
255
256
    /**
257
     * @test
258
     */
259
    public function it_does_not_allow_to_change_product_attribute_type()
260
    {
261
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
262
        $this->loadFixturesFromFile('resources/locales.yml');
263
        $productAttributes = $this->loadFixturesFromFile('resources/product_attributes.yml');
264
        $productAttribute = $productAttributes['productAttribute1'];
265
266
        $data =
267
<<<EOT
268
        {
269
            "type": "integer"
270
        }
271
EOT;
272
273
        $this->client->request('PATCH', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithContentType, $data);
274
275
        $response = $this->client->getResponse();
276
        $this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
277
278
        $this->client->request('GET', $this->getProductAttributeUrl($productAttribute), [], [], static::$authorizedHeaderWithAccept);
279
280
        $response = $this->client->getResponse();
281
        $this->assertResponse($response, 'product_attribute/show_response', Response::HTTP_OK);
282
    }
283
284
    /**
285
     * @test
286
     */
287
    public function it_allows_to_create_select_product_attribute()
288
    {
289
        $this->loadFixturesFromFile('authentication/api_administrator.yml');
290
        $this->loadFixturesFromFile('resources/locales.yml');
291
292
        $data =
293
<<<EOT
294
        {
295
            "code": "mug_color",
296
            "configuration": {
297
                "choices": [
298
                    "yellow",
299
                    "green",
300
                    "black"
301
                ],
302
                "multiple": true,
303
                "min": 1,
304
                "max": 2
305
            },
306
            "translations": {
307
                "de_CH": {
308
                    "name": "Becher Farbe"
309
                },
310
                "en_US": {
311
                    "name": "Mug color"
312
                }
313
            }
314
        }
315
EOT;
316
317
        $this->client->request('POST', '/api/v1/product-attributes/select', [], [], static::$authorizedHeaderWithContentType, $data);
318
319
        $response = $this->client->getResponse();
320
        $this->assertResponse($response, 'product_attribute/create_select_response', Response::HTTP_CREATED);
321
        $this->assertSelectChoicesInResponse($response, ['yellow', 'green', 'black']);
322
    }
323
324
    /**
325
     * @param ProductAttributeInterface $productAttribute
326
     *
327
     * @return string
328
     */
329
    private function getProductAttributeUrl(ProductAttributeInterface $productAttribute)
330
    {
331
        return '/api/v1/product-attributes/' . $productAttribute->getCode();
332
    }
333
334
    /**
335
     * @param Response $response
336
     * @param array|string[] $expectedChoiceValues
337
     */
338
    private function assertSelectChoicesInResponse(Response $response, array $expectedChoiceValues): void
339
    {
340
        $responseContent = json_decode($response->getContent(), true);
341
        Assert::assertArrayHasKey('configuration', $responseContent);
342
343
        $configuration = $responseContent['configuration'];
344
        Assert::assertArrayHasKey('choices', $configuration);
345
346
        $choices = $configuration['choices'];
347
        Assert::assertCount(count($expectedChoiceValues), $choices);
348
349
        foreach ($expectedChoiceValues as $expectedChoiceValue) {
350
            Assert::assertContains($expectedChoiceValue, $choices);
351
        }
352
353
        foreach ($choices as $choiceKey => $choiceValue) {
354
            Assert::assertRegExp('/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i', $choiceKey);
355
        }
356
    }
357
}
358