Completed
Push — symfony3-wololo-packages ( fecf70...6bf04d )
by Kamil
28:46 queued 11:35
created

CreateSimpleProductPage::getDefinedElements()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 22
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
namespace Sylius\Behat\Page\Admin\Product;
13
14
use Behat\Mink\Driver\Selenium2Driver;
15
use Behat\Mink\Element\NodeElement;
16
use Behat\Mink\Exception\ElementNotFoundException;
17
use Sylius\Behat\Behaviour\SpecifiesItsCode;
18
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
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
 */
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', ['%channel%' => $channelName])->setValue($price);
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function addAttribute($attribute, $value)
72
    {
73
        $this->clickTabIfItsNotActive('attributes');
74
75
        $attributeOption = $this->getElement('attributes_choice')->find('css', sprintf('option:contains("%s")', $attribute));
76
        $this->selectElementFromAttributesDropdown($attributeOption->getAttribute('value'));
77
78
        $this->getDocument()->pressButton('Add attributes');
79
        $this->waitForFormElement();
80
81
        $this->getElement('attribute_value', ['%attribute%' => $attribute])->setValue($value);
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function removeAttribute($attribute)
88
    {
89
        $this->clickTabIfItsNotActive('attributes');
90
91
        $this->getElement('attribute_delete_button', ['%attribute%' => $attribute])->press();
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function attachImage($path, $code = null)
98
    {
99
        $this->clickTabIfItsNotActive('media');
100
101
        $filesPath = $this->getParameter('files_path');
102
103
        $this->getDocument()->clickLink('Add');
104
105
        $imageForm = $this->getLastImageElement();
106
        if (null !== $code) {
107
            $imageForm->fillField('Code', $code);
108
        }
109
110
        $imageForm->find('css', 'input[type="file"]')->attachFile($filesPath.$path);
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function associateProducts(ProductAssociationTypeInterface $productAssociationType, array $productsNames)
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $productAssociationType exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
117
    {
118
        $this->clickTab('associations');
119
120
        Assert::isInstanceOf($this->getDriver(), Selenium2Driver::class);
121
122
        $dropdown = $this->getElement('association_dropdown', [
123
            '%association%' => $productAssociationType->getName()
124
        ]);
125
        $dropdown->click();
126
127
        foreach ($productsNames as $productName) {
128
            $dropdown->waitFor(5, function () use ($productName, $productAssociationType) {
129
                return $this->hasElement('association_dropdown_item', [
130
                    '%association%' => $productAssociationType->getName(),
131
                    '%item%' => $productName,
132
                ]);
133
            });
134
135
            $item = $this->getElement('association_dropdown_item', [
136
                '%association%' => $productAssociationType->getName(),
137
                '%item%' => $productName,
138
            ]);
139
            $item->click();
140
        }
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public function removeAssociatedProduct($productName, ProductAssociationTypeInterface $productAssociationType)
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $productAssociationType exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
147
    {
148
        $this->clickTabIfItsNotActive('associations');
149
150
        $item = $this->getElement('association_dropdown_item_selected', [
151
            '%association%' => $productAssociationType->getName(),
152
            '%item%' => $productName,
153
        ]);
154
        $item->find('css', 'i.delete')->click();
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function choosePricingCalculator($name)
161
    {
162
        $this->getElement('price_calculator')->selectOption($name);
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168
    public function checkChannel($channelName)
169
    {
170
        $this->getElement('channel_checkbox', ['%channel%' => $channelName])->check();
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176
    public function specifyPriceForChannelAndCurrency($price, ChannelInterface $channel, CurrencyInterface $currency)
177
    {
178
        $calculatorElement = $this->getElement('calculator');
179
        $calculatorElement
180
            ->waitFor(5, function () use ($channel, $currency) {
181
                return $this->getElement('calculator')->hasField(sprintf('%s %s', $channel->getName(), $currency->getCode()));
182
            })
183
        ;
184
185
        $calculatorElement->fillField(sprintf('%s %s', $channel->getName(), $currency->getCode()), $price);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191
    public function activateLanguageTab($locale)
192
    {
193
        if (!$this->getDriver() instanceof Selenium2Driver) {
194
            return;
195
        }
196
197
        $languageTabTitle = $this->getElement('language_tab', ['%locale%' => $locale]);
198
        if (!$languageTabTitle->hasClass('active')) {
199
            $languageTabTitle->click();
200
        }
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206
    public function selectShippingCategory($shippingCategoryName)
207
    {
208
        $this->getElement('shipping_category')->selectOption($shippingCategoryName);
209
    }
210
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    protected function getElement($name, array $parameters = [])
216
    {
217
        if (!isset($parameters['%locale%'])) {
218
            $parameters['%locale%'] = 'en_US';
219
        }
220
221
        return parent::getElement($name, $parameters);
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227
    protected function getDefinedElements()
228
    {
229
        return array_merge(parent::getDefinedElements(), [
230
            'association_dropdown' => '.field > label:contains("%association%") ~ .product-select',
231
            'association_dropdown_item' => '.field > label:contains("%association%") ~ .product-select > div.menu > div.item:contains("%item%")',
232
            'association_dropdown_item_selected' => '.field > label:contains("%association%") ~ .product-select > a.label:contains("%item%")',
233
            'attribute_delete_button' => '.attribute .label:contains("%attribute%") ~ button',
234
            'attribute_value' => '.attribute .label:contains("%attribute%") ~ input',
235
            'attributes_choice' => '#sylius_product_attribute_choice',
236
            'calculator' => '#sylius_calculator_container',
237
            'channel_checkbox' => '.checkbox:contains("%channel%") input',
238
            'channel_pricings' => '#sylius_product_variant_channelPricings',
239
            'code' => '#sylius_product_code',
240
            'form' => 'form[name="sylius_product"]',
241
            'images' => '#sylius_product_images',
242
            'language_tab' => '[data-locale="%locale%"] .title',
243
            'name' => '#sylius_product_translations_%locale%_name',
244
            'price' => '#sylius_product_variant_channelPricings [data-form-collection="item"]:contains("%channel%") input',
245
            'price_calculator' => '#sylius_product_variant_pricingCalculator',
246
            'shipping_category' => '#sylius_product_variant_shippingCategory',
247
            'slug' => '#sylius_product_translations_%locale%_slug',
248
            'tab' => '.menu [data-tab="%name%"]',
249
            'toggle_slug_modification_button' => '.toggle-product-slug-modification',
250
        ]);
251
    }
252
253
    /**
254
     * @param int $id
255
     */
256
    private function selectElementFromAttributesDropdown($id)
257
    {
258
        /** @var Selenium2Driver $driver */
259
        $driver = $this->getDriver();
260
        Assert::isInstanceOf($driver, Selenium2Driver::class);
261
262
        $driver->executeScript('$(\'#sylius_product_attribute_choice\').dropdown(\'show\');');
263
        $driver->executeScript(sprintf('$(\'#sylius_product_attribute_choice\').dropdown(\'set selected\', \'%s\');', $id));
264
    }
265
266
    /**
267
     * @param int $timeout
268
     */
269
    private function waitForFormElement($timeout = 5)
270
    {
271
        $form = $this->getElement('form');
272
        $this->getDocument()->waitFor($timeout, function () use ($form) {
273
            return false === strpos($form->getAttribute('class'), 'loading');
274
        });
275
    }
276
277
    /**
278
     * @param string $tabName
279
     */
280
    private function clickTabIfItsNotActive($tabName)
281
    {
282
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
283
        if (!$attributesTab->hasClass('active')) {
284
            $attributesTab->click();
285
        }
286
    }
287
288
    /**
289
     * @param string $tabName
290
     */
291
    private function clickTab($tabName)
292
    {
293
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
294
        $attributesTab->click();
295
    }
296
297
    /**
298
     * @return NodeElement
299
     */
300
    private function getLastImageElement()
301
    {
302
        $images = $this->getElement('images');
303
        $items = $images->findAll('css', 'div[data-form-collection="item"]');
304
305
        Assert::notEmpty($items);
306
307
        return end($items);
308
    }
309
310
    /**
311
     * @param string $locale
312
     */
313
    private function waitForSlugGenerationIfNecessary($locale)
314
    {
315
        if ($this->getDriver() instanceof Selenium2Driver) {
316
            $this->getDocument()->waitFor(10, function () use ($locale) {
317
                return '' !== $this->getElement('slug', ['%locale%' => $locale])->getValue();
318
            });
319
        }
320
    }
321
}
322