Completed
Push — master ( ab6ee6...8da333 )
by Kamil
32:30 queued 09:03
created

iDoNotSpecifyTheProvinceCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
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\Behat\Context\Api\Admin;
15
16
use ApiPlatform\Core\Api\IriConverterInterface;
17
use Behat\Behat\Context\Context;
18
use Sylius\Behat\Client\ApiClientInterface;
19
use Sylius\Behat\Client\ResponseCheckerInterface;
20
use Sylius\Behat\Service\SharedStorageInterface;
21
use Sylius\Component\Addressing\Model\CountryInterface;
22
use Sylius\Component\Addressing\Model\Province;
23
use Sylius\Component\Addressing\Model\ProvinceInterface;
24
use Symfony\Component\Intl\Countries;
25
use Webmozart\Assert\Assert;
26
27
final class ManagingCountriesContext implements Context
28
{
29
    /** @var ApiClientInterface */
30
    private $client;
31
32
    /** @var ApiClientInterface */
33
    private $provincesClient;
34
35
    /** @var ResponseCheckerInterface */
36
    private $responseChecker;
37
38
    /** @var SharedStorageInterface */
39
    private $sharedStorage;
40
41
    /** @var IriConverterInterface */
42
    private $iriConverter;
43
44
    public function __construct(
45
        ApiClientInterface $client,
46
        ApiClientInterface $provincesClient,
47
        ResponseCheckerInterface $responseChecker,
48
        SharedStorageInterface $sharedStorage,
49
        IriConverterInterface $iriConverter
50
    ) {
51
        $this->client = $client;
52
        $this->provincesClient = $provincesClient;
53
        $this->responseChecker = $responseChecker;
54
        $this->sharedStorage = $sharedStorage;
55
        $this->iriConverter = $iriConverter;
56
    }
57
58
    /**
59
     * @When I want to add a new country
60
     */
61
    public function iWantToAddANewCountry(): void
62
    {
63
        $this->client->buildCreateRequest();
64
    }
65
66
    /**
67
     * @When I choose :countryName
68
     */
69
    public function iChoose(string $countryName): void
70
    {
71
        $this->client->addRequestData('code', $this->getCountryCodeByName($countryName));
72
    }
73
74
    /**
75
     * @When I add it
76
     */
77
    public function iAddIt(): void
78
    {
79
        $this->client->create();
80
    }
81
82
    /**
83
     * @When /^I want to edit (this country)$/
84
     * @When /^I want to create a new province in (country "([^"]+)")$/
85
     */
86
    public function iWantToEditThisCountry(CountryInterface $country): void
87
    {
88
        $this->client->buildUpdateRequest($country->getCode());
89
    }
90
91
    /**
92
     * @When I enable it
93
     */
94
    public function iEnableIt(): void
95
    {
96
        $this->client->addRequestData('enabled', true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string|integer|array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
97
    }
98
99
    /**
100
     * @When I disable it
101
     */
102
    public function iDisableIt(): void
103
    {
104
        $this->client->addRequestData('enabled', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string|integer|array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
105
    }
106
107
    /**
108
     * @When I save my changes
109
     * @When I try to save changes
110
     */
111
    public function iSaveMyChanges(): void
112
    {
113
        $this->client->update();
114
    }
115
116
    /**
117
     * @When I name the province :provinceName
118
     */
119
    public function iNameTheProvince(string $provinceName): void
120
    {
121
        $this->client->addSubResourceData(
122
            'provinces',
123
            ['name' => $provinceName]
124
        );
125
    }
126
127
    /**
128
     * @When I specify the province code as :provinceCode
129
     */
130
    public function iSpecifyTheProvinceCodeAs(string $provinceCode): void
131
    {
132
        $this->client->addSubResourceData(
133
            'provinces',
134
            ['code' => $provinceCode]
135
        );
136
    }
137
138
    /**
139
     * @When I add the :provinceName province with :provinceCode code
140
     */
141
    public function iAddTheProvinceWithCode(string $provinceName, string $provinceCode): void
142
    {
143
        $this->client->addSubResourceData(
144
            'provinces',
145
            ['code' => $provinceCode, 'name' => $provinceName]
146
        );
147
    }
148
149
    /**
150
     * @When I add the :name province with :code code and :abbreviation abbreviation
151
     */
152
    public function iAddTheProvinceWithCodeAndAbbreviation(string $name, string $code, string $abbreviation): void
153
    {
154
        $this->client->addSubResourceData(
155
            'provinces',
156
            ['code' => $code, 'name' => $name, 'abbreviation' => $abbreviation]
157
        );
158
    }
159
160
    /**
161
     * @When /^I delete the ("[^"]+" province) of (this country)$/
162
     */
163
    public function iDeleteTheProvinceOfThisCountry(ProvinceInterface $province, CountryInterface $country): void
164
    {
165
        $iri = $this->iriConverter->getItemIriFromResourceClass(Province::class, ['code' => $province->getCode()]);
166
167
        $provinces = $this->responseChecker->getValue($this->client->show($country->getCode()), 'provinces');
168
        foreach ($provinces as $countryProvince) {
169
            if ($iri === $countryProvince) {
170
                $this->client->removeSubResource('provinces', $countryProvince);
171
            }
172
        }
173
    }
174
175
    /**
176
     * @When I do not specify the province code
177
     * @When I do not name the province
178
     */
179
    public function iDoNotSpecifyTheProvince(): void
180
    {
181
        // Intentionally left blank
182
    }
183
184
    /**
185
     * @When I remove :province province name
186
     */
187
    public function iRemoveProvinceName(ProvinceInterface $province): void
188
    {
189
        $this->provincesClient->buildUpdateRequest($province->getCode());
190
        $this->provincesClient->addRequestData('name', '');
191
        $this->provincesClient->update();
192
    }
193
194
    /**
195
     * @Then I should be notified that it has been successfully created
196
     */
197
    public function iShouldBeNotifiedThatItHasBeenSuccessfullyCreated(): void
198
    {
199
        Assert::true(
200
            $this->responseChecker->isCreationSuccessful($this->client->getLastResponse()),
201
            'Country could not be created'
202
        );
203
    }
204
205
    /**
206
     * @Then the country :country should appear in the store
207
     */
208
    public function theCountryShouldAppearInTheStore(CountryInterface $country): void
209
    {
210
        Assert::true(
211
            $this->responseChecker->hasItemWithValue($this->client->index(), 'code', $country->getCode()),
212
            sprintf('There is no country with name "%s"', $country->getName())
213
        );
214
    }
215
216
    /**
217
     * @Then the country :country should have the :province province
218
     * @Then /^(this country) should have the ("[^"]*" province)$/
219
     */
220
    public function theCountryShouldHaveTheProvince(CountryInterface $country, ProvinceInterface $province): void
221
    {
222
        Assert::true($this->responseChecker->hasItemWithValue(
223
            $this->client->subResourceIndex('provinces', $country->getCode()),
224
            'code',
225
            $province->getCode()
226
        ));
227
    }
228
229
    /**
230
     * @Then the province should still be named :province in this country
231
     */
232
    public function theProvinceShouldStillBeNamedInThisCountry(ProvinceInterface $province): void
233
    {
234
        /** @var CountryInterface $country */
235
        $country = $this->sharedStorage->get('country');
236
        Assert::true($this->responseChecker->hasItemWithValue(
237
            $this->client->subResourceIndex('provinces', $country->getCode()),
238
            'code',
239
            $province->getCode()
240
        ));
241
    }
242
243
    /**
244
     * @Then I should not be able to choose :countryName
245
     */
246
    public function iShouldNotBeAbleToChoose(string $countryName): void
247
    {
248
        $this->client->addRequestData('code', $this->getCountryCodeByName($countryName));
249
        $response = $this->client->create();
250
        Assert::false(
251
            $this->responseChecker->isCreationSuccessful($response),
252
            'Country has been created successfully, but it should not'
253
        );
254
        Assert::same($this->responseChecker->getError($response), 'code: Country ISO code must be unique.');
255
    }
256
257
    /**
258
     * @Then I should be notified that it has been successfully edited
259
     */
260
    public function iShouldBeNotifiedThatItHasBeenSuccessfullyEdited(): void
261
    {
262
        Assert::true(
263
            $this->responseChecker->isUpdateSuccessful($this->client->getLastResponse()),
264
            'Country could not be edited'
265
        );
266
    }
267
268
    /**
269
     * @Then /^(this country) should be (enabled|disabled)$/
270
     */
271
    public function thisCountryShouldBeDisabled(CountryInterface $country, string $enabled): void
272
    {
273
        Assert::true(
274
            $this->responseChecker->hasValue(
275
                $this->client->show($country->getCode()),
276
                'enabled',
277
                $enabled === 'enabled' ? true : false
0 ignored issues
show
Documentation introduced by
$enabled === 'enabled' ? true : false is of type boolean, but the function expects a string|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
278
            ),
279
            'Country is not disabled'
280
        );
281
    }
282
283
    /**
284
     * @Then I should not be able to edit its code
285
     */
286
    public function theCodeFieldShouldBeDisabled(): void
287
    {
288
        $this->client->updateRequestData(['code' => 'NEW_CODE']);
289
290
        Assert::false($this->responseChecker->hasValue($this->client->update(), 'code', 'NEW_CODE'));
291
    }
292
293
    /**
294
     * @Then /^province with code ("[^"]*") should not be added in (this country)$/
295
     */
296
    public function provinceWithCodeShouldNotBeAddedInThisCountry(string $provinceCode, CountryInterface $country): void
297
    {
298
        /** @var ProvinceInterface $province */
299
        foreach ($this->getProvincesOfCountry($country) as $province) {
300
            Assert::false(
301
                $province->getCode() === $provinceCode,
302
                sprintf('The country "%s" should not have the "%s" province', $country->getName(), $province->getName())
303
            );
304
        }
305
    }
306
307
    /**
308
     * @Then this country should not have the :provinceName province
309
     * @Then province with name :provinceName should not be added in this country
310
     */
311
    public function thisCountryShouldNotHaveTheProvince(string $provinceName): void
312
    {
313
        /** @var CountryInterface $country */
314
        $country = $this->sharedStorage->get('country');
315
        /** @var ProvinceInterface $province */
316
        foreach ($this->getProvincesOfCountry($country) as $province) {
317
            Assert::false(
318
                $province->getName() === $provinceName,
319
                sprintf('The country "%s" should not have the "%s" province', $country->getName(), $province->getName())
320
            );
321
        }
322
    }
323
324
    /**
325
     * @Then I should be notified that province code must be unique
326
     */
327
    public function iShouldBeNotifiedThatProvinceCodeMustBeUnique(): void
328
    {
329
        Assert::same(
330
            $this->responseChecker->getError($this->client->getLastResponse()),
331
            'provinces[1].code: Province code must be unique.'
332
        );
333
    }
334
335
    /**
336
     * @Then I should be notified that :field is required
337
     */
338
    public function iShouldBeNotifiedThatFieldIsRequired(string $field): void
339
    {
340
        Assert::contains(
341
            $this->responseChecker->getError($this->client->getLastResponse()),
342
            \sprintf('Please enter province %s.', $field)
343
        );
344
    }
345
346
    /**
347
     * @Then I should be notified that name of the province is required
348
     */
349
    public function iShouldBeNotifiedThatNameOfTheProvinceIsRequired(): void
350
    {
351
        Assert::contains(
352
            $this->responseChecker->getError($this->provincesClient->getLastResponse()),
353
            'Please enter province name.'
354
        );
355
    }
356
357
    private function getCountryCodeByName(string $countryName): string
358
    {
359
        $countryList = array_flip(Countries::getNames());
360
        Assert::keyExists(
361
            $countryList,
362
            $countryName,
363
            sprintf('The country with name "%s" not found', $countryName)
364
        );
365
366
        return $countryList[$countryName];
367
    }
368
369
    private function getProvincesOfCountry(CountryInterface $country): iterable
370
    {
371
        $response = $this->client->show($country->getCode());
372
        $countryFromResponse = $this->responseChecker->getResponseContent($response);
373
374
        foreach ($countryFromResponse['provinces'] as $provinceFromResponse) {
375
            yield $this->iriConverter->getItemFromIri($provinceFromResponse);
376
        }
377
    }
378
}
379