Completed
Push — master ( 968507...279808 )
by Paweł
10:20
created

CreateSimpleProductPage::setShippingRequired()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
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
namespace Sylius\Behat\Page\Admin\Product;
13
14
use Behat\Mink\Driver\Selenium2Driver;
15
use Behat\Mink\Element\NodeElement;
16
use Sylius\Behat\Behaviour\SpecifiesItsCode;
17
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
18
use Sylius\Component\Core\Model\ChannelInterface;
19
use Sylius\Component\Currency\Model\CurrencyInterface;
20
use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
21
use Webmozart\Assert\Assert;
22
23
/**
24
 * @author Łukasz Chruściel <[email protected]>
25
 * @author Gorka Laucirica <[email protected]>
26
 */
27
class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProductPageInterface
28
{
29
    use SpecifiesItsCode;
30
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public function getRouteName()
35
    {
36
        return parent::getRouteName() . '_simple';
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function nameItIn($name, $localeCode)
43
    {
44
        $this->activateLanguageTab($localeCode);
45
        $this->getElement('name', ['%locale%' => $localeCode])->setValue($name);
46
47
        $this->waitForSlugGenerationIfNecessary($localeCode);
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function specifySlugIn($slug, $locale)
54
    {
55
        $this->activateLanguageTab($locale);
56
57
        $this->getElement('slug', ['%locale%' => $locale])->setValue($slug);
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function specifyPrice($channelName, $price)
64
    {
65
        $this->getElement('price', ['%channelName%' => $channelName])->setValue($price);
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function specifyOriginalPrice($channelName, $originalPrice)
72
    {
73
        $this->getElement('original_price', ['%channelName%' => $channelName])->setValue($originalPrice);
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function addAttribute($attributeName, $value, $localeCode)
80
    {
81
        $this->clickTabIfItsNotActive('attributes');
82
        $this->clickLocaleTabIfItsNotActive($localeCode);
83
84
        $attributeOption = $this->getElement('attributes_choice')->find('css', sprintf('option:contains("%s")', $attributeName));
85
        $this->selectElementFromAttributesDropdown($attributeOption->getAttribute('value'));
86
87
        $this->getDocument()->pressButton('Add attributes');
88
        $this->waitForFormElement();
89
90
        $this->getElement('attribute_value', ['%attributeName%' => $attributeName, '%localeCode%' => $localeCode])->setValue($value);
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function removeAttribute($attributeName, $localeCode)
97
    {
98
        $this->clickTabIfItsNotActive('attributes');
99
100
        $this->getElement('attribute_delete_button', ['%attributeName%' => $attributeName, '%localeCode%' => $localeCode])->press();
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function attachImage($path, $type = null)
107
    {
108
        $this->clickTabIfItsNotActive('media');
109
110
        $filesPath = $this->getParameter('files_path');
111
112
        $this->getDocument()->clickLink('Add');
113
114
        $imageForm = $this->getLastImageElement();
115
        if (null !== $type) {
116
            $imageForm->fillField('Type', $type);
117
        }
118
119
        $imageForm->find('css', 'input[type="file"]')->attachFile($filesPath.$path);
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function associateProducts(ProductAssociationTypeInterface $productAssociationType, array $productsNames)
126
    {
127
        $this->clickTab('associations');
128
129
        Assert::isInstanceOf($this->getDriver(), Selenium2Driver::class);
130
131
        $dropdown = $this->getElement('association_dropdown', [
132
            '%association%' => $productAssociationType->getName()
133
        ]);
134
        $dropdown->click();
135
136
        foreach ($productsNames as $productName) {
137
            $dropdown->waitFor(5, function () use ($productName, $productAssociationType) {
138
                return $this->hasElement('association_dropdown_item', [
139
                    '%association%' => $productAssociationType->getName(),
140
                    '%item%' => $productName,
141
                ]);
142
            });
143
144
            $item = $this->getElement('association_dropdown_item', [
145
                '%association%' => $productAssociationType->getName(),
146
                '%item%' => $productName,
147
            ]);
148
            $item->click();
149
        }
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function removeAssociatedProduct($productName, ProductAssociationTypeInterface $productAssociationType)
156
    {
157
        $this->clickTabIfItsNotActive('associations');
158
159
        $item = $this->getElement('association_dropdown_item_selected', [
160
            '%association%' => $productAssociationType->getName(),
161
            '%item%' => $productName,
162
        ]);
163
        $item->find('css', 'i.delete')->click();
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169
    public function choosePricingCalculator($name)
170
    {
171
        $this->getElement('price_calculator')->selectOption($name);
172
    }
173
174
    /**
175
     * {@inheritdoc}
176
     */
177
    public function checkChannel($channelName)
178
    {
179
        $this->getElement('channel_checkbox', ['%channelName%' => $channelName])->check();
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185
    public function specifyPriceForChannelAndCurrency($price, ChannelInterface $channel, CurrencyInterface $currency)
186
    {
187
        $calculatorElement = $this->getElement('calculator');
188
        $calculatorElement
189
            ->waitFor(5, function () use ($channel, $currency) {
190
                return $this->getElement('calculator')->hasField(sprintf('%s %s', $channel->getName(), $currency->getCode()));
191
            })
192
        ;
193
194
        $calculatorElement->fillField(sprintf('%s %s', $channel->getName(), $currency->getCode()), $price);
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function activateLanguageTab($locale)
201
    {
202
        if (!$this->getDriver() instanceof Selenium2Driver) {
203
            return;
204
        }
205
206
        $languageTabTitle = $this->getElement('language_tab', ['%locale%' => $locale]);
207
        if (!$languageTabTitle->hasClass('active')) {
208
            $languageTabTitle->click();
209
        }
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function selectShippingCategory($shippingCategoryName)
216
    {
217
        $this->getElement('shipping_category')->selectOption($shippingCategoryName);
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223
    public function setShippingRequired($isShippingRequired)
224
    {
225
        if ($isShippingRequired) {
226
            $this->getElement('shipping_required')->check();
227
228
            return;
229
        }
230
231
        $this->getElement('shipping_required')->uncheck();
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237
    protected function getElement($name, array $parameters = [])
238
    {
239
        if (!isset($parameters['%locale%'])) {
240
            $parameters['%locale%'] = 'en_US';
241
        }
242
243
        return parent::getElement($name, $parameters);
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249
    protected function getDefinedElements()
250
    {
251
        return array_merge(parent::getDefinedElements(), [
252
            'association_dropdown' => '.field > label:contains("%association%") ~ .product-select',
253
            'association_dropdown_item' => '.field > label:contains("%association%") ~ .product-select > div.menu > div.item:contains("%item%")',
254
            'association_dropdown_item_selected' => '.field > label:contains("%association%") ~ .product-select > a.label:contains("%item%")',
255
            'attribute_delete_button' => '.tab[data-tab="%localeCode%"] .attribute .label:contains("%attributeName%") ~ button',
256
            'attribute_value' => '.tab[data-tab="%localeCode%"] .attribute .label:contains("%attributeName%") ~ input',
257
            'attributes_choice' => '#sylius_product_attribute_choice',
258
            'calculator' => '#sylius_calculator_container',
259
            'channel_checkbox' => '.checkbox:contains("%channelName%") input',
260
            'channel_pricings' => '#sylius_product_variant_channelPricings',
261
            'code' => '#sylius_product_code',
262
            'form' => 'form[name="sylius_product"]',
263
            'images' => '#sylius_product_images',
264
            'language_tab' => '[data-locale="%locale%"] .title',
265
            'locale_tab' => '#attributesContainer .menu [data-tab="%localeCode%"]',
266
            'name' => '#sylius_product_translations_%locale%_name',
267
            'price' => '#sylius_product_variant_channelPricings > .field:contains("%channelName%") input[name$="[price]"]',
268
            'original_price' => '#sylius_product_variant_channelPricings > .field:contains("%channelName%") input[name$="[originalPrice]"]',
269
            'price_calculator' => '#sylius_product_variant_pricingCalculator',
270
            'shipping_category' => '#sylius_product_variant_shippingCategory',
271
            'shipping_required' => '#sylius_product_variant_shippingRequired',
272
            'slug' => '#sylius_product_translations_%locale%_slug',
273
            'tab' => '.menu [data-tab="%name%"]',
274
            'toggle_slug_modification_button' => '.toggle-product-slug-modification',
275
        ]);
276
    }
277
278
    /**
279
     * @param int $id
280
     */
281
    private function selectElementFromAttributesDropdown($id)
282
    {
283
        /** @var Selenium2Driver $driver */
284
        $driver = $this->getDriver();
285
        Assert::isInstanceOf($driver, Selenium2Driver::class);
286
287
        $driver->executeScript('$(\'#sylius_product_attribute_choice\').dropdown(\'show\');');
288
        $driver->executeScript(sprintf('$(\'#sylius_product_attribute_choice\').dropdown(\'set selected\', \'%s\');', $id));
289
    }
290
291
    /**
292
     * @param int $timeout
293
     */
294
    private function waitForFormElement($timeout = 5)
295
    {
296
        $form = $this->getElement('form');
297
        $this->getDocument()->waitFor($timeout, function () use ($form) {
298
            return false === strpos($form->getAttribute('class'), 'loading');
299
        });
300
    }
301
302
    /**
303
     * @param string $tabName
304
     */
305
    private function clickTabIfItsNotActive($tabName)
306
    {
307
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
308
        if (!$attributesTab->hasClass('active')) {
309
            $attributesTab->click();
310
        }
311
    }
312
313
    /**
314
     * @param string $tabName
315
     */
316
    private function clickTab($tabName)
317
    {
318
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
319
        $attributesTab->click();
320
    }
321
322
    /**
323
     * @param string $localeCode
324
     */
325
    private function clickLocaleTabIfItsNotActive($localeCode)
326
    {
327
        $localeTab = $this->getElement('locale_tab', ['%localeCode%' => $localeCode]);
328
        if (!$localeTab->hasClass('active')) {
329
            $localeTab->click();
330
        }
331
    }
332
333
    /**
334
     * @return NodeElement
335
     */
336
    private function getLastImageElement()
337
    {
338
        $images = $this->getElement('images');
339
        $items = $images->findAll('css', 'div[data-form-collection="item"]');
340
341
        Assert::notEmpty($items);
342
343
        return end($items);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression end($items); of type Behat\Mink\Element\NodeElement|false adds false to the return on line 343 which is incompatible with the return type documented by Sylius\Behat\Page\Admin\...ge::getLastImageElement of type Behat\Mink\Element\NodeElement. It seems like you forgot to handle an error condition.
Loading history...
344
    }
345
346
    /**
347
     * @param string $locale
348
     */
349
    private function waitForSlugGenerationIfNecessary($locale)
350
    {
351
        if ($this->getDriver() instanceof Selenium2Driver) {
352
            $this->getDocument()->waitFor(10, function () use ($locale) {
353
                return '' !== $this->getElement('slug', ['%locale%' => $locale])->getValue();
354
            });
355
        }
356
    }
357
}
358