Completed
Push — master ( 1d849e...3a997f )
by Paweł
09:48
created

CreateSimpleProductPage::waitForSlugGenerationIfNecessary()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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